package com.simdo.g768;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Vibrator;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager2.widget.ViewPager2;

import com.g768.Bean.BusinessRsp;
import com.g768.Bean.JsonObject;
import com.g768.Bean.LteBand;
import com.g768.Bean.NrBand;
import com.g768.Bean.PaPkUlArfcnBean;
import com.g768.Bean.UeidBean;
import com.g768.Constant.CmdConstant;
import com.g768.Constant.ConnectConstant;
import com.g768.G768Sdk;
import com.g768.Interface.BusinessListener;
import com.g768.Interface.SocketChangeListener;
import com.g768.MessageControl.MessageController;
import com.g768.Util.IpUtil;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import com.google.gson.reflect.TypeToken;
import com.simdo.g768.Adapter.FragmentAdapter;
import com.simdo.g768.Adapter.FreqResultListAdapter;
import com.simdo.g768.Adapter.StepAdapter;
import com.simdo.g768.Bean.ArfcnPciBean;
import com.simdo.g768.Bean.DeviceInfo;
import com.simdo.g768.Bean.ErrResultInfo;
import com.simdo.g768.Bean.GnbBean;
import com.simdo.g768.Bean.HistoryBean;
import com.simdo.g768.Bean.IMSIState;
import com.simdo.g768.Bean.ImsiBean;
import com.simdo.g768.Bean.MyUeidBean;
import com.simdo.g768.Bean.ScanArfcnBean;
import com.simdo.g768.Bean.StepBean;
import com.simdo.g768.Bean.TraceBean;
import com.simdo.g768.Bean.object.CatchConfig;
import com.simdo.g768.Bean.object.Cell_info;
import com.simdo.g768.Bean.object.ControlConfig;
import com.simdo.g768.Bean.object.Gnb_cfg;
import com.simdo.g768.Bean.object.Heartbeat;
import com.simdo.g768.Bean.object.Pa_cfg;
import com.simdo.g768.Bean.object.TraceConfig;
import com.simdo.g768.Bean.object.Trace_cfg;
import com.simdo.g768.Dialog.AutoFreqDialog;
import com.simdo.g768.Dialog.CustomDialog;
import com.simdo.g768.Dialog.DoRfDialog;
import com.simdo.g768.Dialog.GuideDialog;
import com.simdo.g768.File.FileUtil;
import com.simdo.g768.Fragment.CatchChildFragment;
import com.simdo.g768.Fragment.CfgTraceChildFragment;
import com.simdo.g768.Fragment.TraceChildFragment;
import com.simdo.g768.Fragment.WarningChildFragment;
import com.simdo.g768.Mqtt.MqttBean;
import com.simdo.g768.Mqtt.MqttConnection;
import com.simdo.g768.Mqtt.MqttManage;
import com.simdo.g768.Mqtt.MqttMsg;
import com.simdo.g768.Mqtt.Subscription;
import com.simdo.g768.SQL.DbManage;
import com.simdo.g768.SlideMenu.SlideLeftFragment;
import com.simdo.g768.SlideMenu.SlideRightFragment;
import com.simdo.g768.SlideMenu.SlidingMenu;
import com.simdo.g768.Util.AppLog;
import com.simdo.g768.Util.DataUtil;
import com.simdo.g768.Util.DateUtil;
import com.simdo.g768.Util.FreqUtil;
import com.simdo.g768.Util.GnbCity;
import com.simdo.g768.Util.GsonUtil;
import com.simdo.g768.Util.PaCtl;
import com.simdo.g768.Util.ParseDataUtil;
import com.simdo.g768.Util.PermissionsUtil;
import com.simdo.g768.Util.PrefUtil;
import com.simdo.g768.Util.SoundUtil;
import com.simdo.g768.Util.TextTTS;
import com.simdo.g768.Util.Util;

import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class MainActivity extends BaseActivity implements SocketChangeListener, BusinessListener {

    private static MainActivity instance;
    public Context mContext;
    public Activity mActivity;

    private final List<MyUeidBean> blackList = new ArrayList<>(); // 存储黑/白名单
    public final List<String> dropImsiList = new ArrayList<>();
    public HashMap<Integer, List<String>> cellMap;
    public static DeviceInfo device = null;
    public int scanCount = 2;
    public int nearValue = -3;
    public boolean enableSpecial;
    public int showMinRsrp;
    public boolean isVibrate = true;
    public boolean isCatchAlarm = true;
    public HashMap<String, String> notesMap;
    private int tipType = 0; // 0:未提示  1：电压小于17提示  2：电压小于16提示
    String lastTip = "";
    int isTipCount = 0;
    public final List<HistoryBean> historyList = new ArrayList<>();
    public final List<MqttMsg> mqttList = new ArrayList<>();

    private AutoFreqDialog mAutoFreqDialog = null;
    private CustomDialog customDialog;
    public MqttConnection mqttConnection;
    private SoundUtil mSoundUtil;

    public static MainActivity getInstance() {
        return instance;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        showGuideDialog();

        instance = this;
        mContext = this;
        mActivity = this;
        WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
        screenWidth = windowManager.getDefaultDisplay().getWidth();
        screenHeight = windowManager.getDefaultDisplay().getHeight();

        Window window = getWindow();
        window.setNavigationBarColor(Color.parseColor("#2A72FF"));
        window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

        requestPermissions();
    }

    private long backPressed;

    @Override
    public void onBackPressed() {
        if (backPressed + 2000 > System.currentTimeMillis()) {
            super.onBackPressed();
            //System.exit(0);
            finish();
        } else {
            showToast(getString(R.string.click_again));
            backPressed = System.currentTimeMillis();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        AppLog.I("++++++ MainActivity onDestroy()");
        G768Sdk.build().release();
        unBindService();
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                System.exit(0);
                //android.os.Process.killProcess(android.os.Process.myPid());
            }
        }, 100);
    }

    private void showGuideDialog() {
        int oldGuideVersion = PrefUtil.build().getInt("guide_version", 0);
        int nowGuideVersion = 1;
        if (oldGuideVersion == nowGuideVersion) return;

        PrefUtil.build().putInt("guide_version", nowGuideVersion);
        GuideDialog guideDialog = new GuideDialog(this);
        guideDialog.show();
    }

    private void requestPermissions() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            String[] permissions = new String[]{
                    Manifest.permission.INTERNET,
                    Manifest.permission.ACCESS_WIFI_STATE,
                    Manifest.permission.ACCESS_NETWORK_STATE,
                    Manifest.permission.ACCESS_COARSE_LOCATION
            };
            List<String> list = new ArrayList<>(Arrays.asList(permissions));
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                /*list.add(Manifest.permission.READ_MEDIA_AUDIO);
                list.add(Manifest.permission.READ_MEDIA_IMAGES);
                list.add(Manifest.permission.READ_MEDIA_VIDEO);*/
                list.add(Manifest.permission.NEARBY_WIFI_DEVICES);
                //list.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
            } else {
                list.add(Manifest.permission.READ_EXTERNAL_STORAGE);
                list.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
                list.add(Manifest.permission.ACCESS_FINE_LOCATION);
            }
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R){
                list.add(Manifest.permission.MANAGE_EXTERNAL_STORAGE);
                list.add(Manifest.permission.FOREGROUND_SERVICE);
            }
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                list.add(Manifest.permission.POST_NOTIFICATIONS);
            }
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
                list.add(Manifest.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE);
            }
            permissions = list.toArray(new String[0]);
            PermissionsUtil.getInstance().checkPermissions(this, permissions, permissionsResult);
        } else {
            startActivity();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        PermissionsUtil.getInstance().onRequestPermissionsResult(this, requestCode, permissions, grantResults);
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == PermissionsUtil.getInstance().mRequestCode) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                if (!Environment.isExternalStorageManager())
                    PermissionsUtil.getInstance().showSystemPermissionsSettingDialog(mActivity);
            }
            requestPermissions();
        }
    }

    PermissionsUtil.IPermissionsResult permissionsResult = new PermissionsUtil.IPermissionsResult() {
        @Override
        public void permitPermissions() {
            //处理通过请求后的操作
            startActivity();
        }

        @Override
        public void refusePermissions() {
            //处理被拒绝申请的权限的操作
            showToast(getString(R.string.refuse_tip));
            finish();
        }
    };

    private void startActivity() {
        AppLog.createLogFile("+++ ON CREATE +++");
        // 弹出登录界面
        initView();   // 初始化视图以及监听事件
        initSlideMenu();
        initObject(); // 初始化对象以及数据
        initArfcnData(); // 初始化扫频数据
        startBindService();//绑定服务
        //initMqtt(); // 初始化MQTT
    }

    /**
     * 绑定主服务，
     */
    ServiceConnection connection;
    public void startBindService() {
        AppLog.createLogFile("+++ startBindService +++");
        /*
         * 服务调用
         * 若需要支持前台服务，则按demo代码执行
         * 若不需要，去掉相关 if 条件
         * */
        Intent intent = new Intent(this, MainService.class);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            startForegroundService(intent);
            // 再开SDK
            initSDK();
        }else{
            connection = new ServiceConnection() {
                public void onServiceDisconnected(ComponentName name) {
                    AppLog.D("+++ onServiceDisconnected +++");
                }

                public void onServiceConnected(ComponentName name, IBinder service) {
                    AppLog.D("+++ onServiceConnected +++");
                    // 再开SDK
                    initSDK();
                }
            };
            bindService(intent, connection, Context.BIND_AUTO_CREATE);
        }
    }

    /**
     * 解除绑定主服务
     */
    public void unBindService() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) unbindService(connection);
    }

    private void initMqtt() {
        String mqttInfo = PrefUtil.build().getString("mqtt_info", "");
        MqttBean mqttBean;
        if (mqttInfo.isEmpty()) mqttBean = new MqttBean();
        else mqttBean = GsonUtil.getPerson(mqttInfo, MqttBean.class);

        mqttConnection = new MqttConnection(this, mqttBean, false);

        if (IpUtil.build().checkIP(mqttBean.getHost())) openMqtt();
    }

    public void openMqtt(){
        AppLog.D("MQTT openMqtt");
        MqttManage.build().disconnect();
        mqttList.clear();
        mSlideRightFrag.mqttNotifyDataSetChanged(null);
        MqttManage.build().connect(mqttConnection, new IMqttActionListener() {
            @Override
            public void onSuccess(IMqttToken asyncActionToken) {
                AppLog.D("MQTT connect success");
                MqttManage.build().unsubscribe(mqttConnection.getMqttBean().getPub_topic() + "/#");

                MqttManage.build().subscribe(new Subscription(mqttConnection.getMqttBean().getPub_topic() + "/#", 0), new IMqttActionListener() {
                    @Override
                    public void onSuccess(IMqttToken asyncActionToken) {
                        AppLog.D("MQTT subscribe success, topic = " + mqttConnection.getMqttBean().getPub_topic());
                    }

                    @Override
                    public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                        AppLog.E("MQTT subscribe fail, err = " + exception);
                    }
                });
            }

            @Override
            public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                AppLog.E("MQTT connect fail, err = " + exception);
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        showToast("MQTT connect fail");
                    }
                });
            }
        }, new MqttCallback() {
            @Override
            public void connectionLost(Throwable cause) {
                AppLog.E("MQTT connectionLost, err = " + cause);
            }

            @Override
            public void messageArrived(String topic, MqttMessage message) {
                //Log.d("MqttInfo", "MQTT topic = " + topic + ", message = " + message);
                String str = new String(message.getPayload());
                if (!str.startsWith("{")) return;
                MqttMsg mqttMsg = new MqttMsg(topic, str);
                for (MqttMsg msg : mqttList) {
                    if (msg.getMqttUeBean().getImsi().equals(mqttMsg.getMqttUeBean().getImsi())) return;
                }
                mqttList.add(mqttMsg);
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mSlideRightFrag.mqttNotifyDataSetChanged(mqttMsg);
                    }
                });
            }

            @Override
            public void deliveryComplete(IMqttDeliveryToken token) {

            }
        });
    }

    private void initSDK() {
        G768Sdk.build().changeLogDir(FileUtil.build().getSDPath()); // 修改SDK路径至根目录下
        G768Sdk.build().init(this);
        G768Sdk.build().addConnectListener(this);
        G768Sdk.build().setBusinessListener(this);
    }

    FragmentAdapter fragmentAdapter;
    CfgTraceChildFragment mCfgTraceChildFragment;
    TraceChildFragment mTraceChildFragment;
    CatchChildFragment mCatchChildFragment;
    WarningChildFragment mWarningChildFragment;
    private List<ImsiBean> mImsiList;
    private List<ImsiBean> mWarningImsiList;
    private TextView tv_dev_state, tv_do_btn;
    private TextView tv_gain_btn;
    private int pos = 0;
    ViewPager2 view_pager;

    @SuppressLint("ClickableViewAccessibility")
    private void initView() {
        tv_gain_btn = findViewById(R.id.tv_gain_btn);
        tv_gain_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (device == null) {
                    showToast(getString(R.string.dev_offline));
                    tv_gain_btn.setVisibility(View.GONE);
                    return;
                }
                boolean isNear = tv_gain_btn.getTag().toString().equals("near");
                // 相反处理
                tv_gain_btn.setTag(isNear ? "standard" : "near");
                tv_gain_btn.setBackgroundResource(isNear ? R.drawable.btn_bg_gain : R.drawable.btn_bg_gain_near);
                doSetTxPwrOffset(isNear ? 0 : nearValue);
            }
        });
        tv_gain_btn.setOnTouchListener(moveListener);
        tv_do_btn = findViewById(R.id.tv_do_btn);
        tv_do_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                doWork();
            }
        });
        tv_do_btn.setOnTouchListener(moveListener);
        tv_dev_state = findViewById(R.id.tv_dev_state);
        tv_dev_state.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                menu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
                menu.setMode(SlidingMenu.LEFT);
                menu.showMenu();
            }
        });
        findViewById(R.id.iv_setting).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                menu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
                menu.setMode(SlidingMenu.LEFT_RIGHT);
                menu.showSecondaryMenu();
            }
        });

        setDevState(-1, getString(R.string.not_ready));
        // 加载底部导航标签
        List<Fragment> fragmentList = new ArrayList<>();
        mCfgTraceChildFragment = new CfgTraceChildFragment(mContext);
        mTraceChildFragment = new TraceChildFragment(mContext);
        mCatchChildFragment = new CatchChildFragment(mContext, mImsiList = new ArrayList<>());
        mWarningChildFragment = new WarningChildFragment(mContext, mWarningImsiList = new ArrayList<>());
        fragmentList.add(mCfgTraceChildFragment);
        if (ZApplication.getInstance().isCatch) TextTTS.build().initTTS();
        else fragmentList.add(mTraceChildFragment);
        fragmentList.add(mCatchChildFragment);
        fragmentList.add(mWarningChildFragment);
        String[] titles;
        int[] icons;
        if (ZApplication.getInstance().isCatch){
            titles = new String[]{getString(R.string.cfg_trace), getString(R.string.catch_list), getString(R.string.target_warning)};
            icons = new int[]{R.drawable.location_tab_icon, R.drawable.list_tab_icon, R.drawable.target_warning_icon};
        }else {
            titles = new String[]{getString(R.string.cfg_trace), getString(R.string.target_report), getString(R.string.catch_list), getString(R.string.target_warning)};
            icons = new int[]{R.drawable.location_tab_icon, R.drawable.target_tab_icon, R.drawable.list_tab_icon, R.drawable.target_warning_icon};
        }

        int[] colors = new int[]{Color.parseColor("#2A72FF"), Color.parseColor("#8F9399")}; //选中颜色  正常颜色

        int[][] states = new int[2][]; //状态
        states[0] = new int[]{android.R.attr.state_selected}; //选中
        states[1] = new int[]{}; //默认
        ColorStateList colorList = new ColorStateList(states, colors);

        view_pager = findViewById(R.id.view_pager);
        final TextView main_page_title = findViewById(R.id.main_page_title);
        main_page_title.setText(getString(R.string.cfg_trace));
        view_pager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
            @Override
            public void onPageSelected(int position) {
                main_page_title.setText(titles[position]);
                pos = position;
                setMenuOpenMode(position);
            }
        });
        fragmentAdapter = new FragmentAdapter(getSupportFragmentManager(), getLifecycle(), fragmentList);
        view_pager.setAdapter(fragmentAdapter);
        view_pager.setCurrentItem(0);

        TabLayout tab_layout = findViewById(R.id.tab_layout);
        tab_layout.setTabRippleColorResource(R.color.trans);// 点击无波纹，需动态设置
        TabLayoutMediator tab = new TabLayoutMediator(tab_layout, view_pager, new TabLayoutMediator.TabConfigurationStrategy() {
            @Override
            public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
                View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.item_tab, null);

                TextView tv_tab_name = view.findViewById(R.id.tv_tab_name);
                tv_tab_name.setText(titles[position]);
                tv_tab_name.setTextColor(colorList);

                ImageView iv_tab_icon = view.findViewById(R.id.iv_tab_icon);
                iv_tab_icon.setImageResource(icons[position]);
                tab.setCustomView(view);
            }
        });
        tab.attach();
    }

    private float lastX = 0;
    private float lastY = 0;
    private float beginX = 0;
    private float beginY = 0;
    private int screenWidth = 0;
    private int screenHeight = 0;

    View.OnTouchListener moveListener = new View.OnTouchListener() {
        @SuppressLint("ClickableViewAccessibility")
        @Override
        public boolean onTouch(View view, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    //限制左右滑动
                    menu.setStatic(true);
                    //获取点击时x y 轴的数据
                    lastX = event.getRawX();
                    lastY = event.getRawY();
                    // 记录控件开始位置
                    beginX = lastX;
                    beginY = lastY;
                    break;
                case MotionEvent.ACTION_MOVE:
                    //获得x y轴的偏移量
                    int dx = (int) (event.getRawX() - lastX);
                    int dy = (int) (event.getRawY() - lastY);
                    //获得控件上下左右的位置信息,加上我们的偏移量,新得到的位置就是我们控件将要出现的位置
                    int l = view.getLeft() + dx;
                    int t = view.getTop() + dy;
                    int r = view.getRight() + dx;
                    int b = view.getBottom() + dy;
                    //判断四个实际位置,如果有一边已经划出屏幕,那就把这边位置设置为0然后相反的边的位置就设置成控件的高度或者宽度
                    if (l < 0) {
                        l = 0;
                        r = l + view.getWidth();
                    } else if (r > screenWidth) {
                        r = screenWidth;
                        l = r - view.getWidth();
                    }
                    if (t < 0) {
                        t = 0;
                        b = t + view.getHeight();
                    } else if (b > screenHeight - 50) {
                        b = screenHeight - 50;
                        t = b - view.getHeight();
                    }
                    //然后使用我们view的layout重新在布局中把我们的控件画出来
                    view.layout(l, t, r, b);
                    //并把现在的x y设置给lastX lastY
                    lastX = (int) event.getRawX();
                    lastY = (int) event.getRawY();
                    //绘制
                    view.postInvalidate();
                    break;
                case MotionEvent.ACTION_UP:
                    // 恢复左右滑动
                    menu.setStatic(false);
                    // 解决拖拽的时候松手点击事件触发
                    if (Math.abs(lastX - beginX) > 10 || Math.abs(lastY - beginY) > 10) return true;
                    break;
            }
            return false;
        }
    };

    boolean[] isChangeImsi = new boolean[]{false, false, false, false, false, false};

    private void doWork() {
        String text = tv_do_btn.getText().toString();
        if (text.equals(getString(R.string.open))) {
            if (device == null) {
                showToast(getString(R.string.dev_offline));
                return;
            }
            if (device.getWorkState() != GnbBean.State.IDLE) {
                showToast(getString(R.string.dev_busy_please_wait));
                return;
            }
            double vol = device.getVoltage()[1];
            if (vol < 1) {
            } else if (vol < 16.6) {
                //showRemindDialog(getString(R.string.vol_min_title), getString(R.string.vol_min_tip));
                //return;
            }

            startRunWork();

        } else if (text.equals(getString(R.string.stop))) {
            stopTraceDialog();
        } else if (text.equals(getString(R.string.starting))) {
            showToast(getString(R.string.starting_cannot_fast));
        } else if (text.equals(getString(R.string.stoping))) {
            showToast(getString(R.string.stoping_cannot_fast));
        }
    }

    private void doSetTxPwrOffset(final int value) {
        AppLog.I("doSetTxPwrOffset rxValue = " + value);

        String id = device.getId();
        int delay = 0;
        for (int cell_id = 0; cell_id < 6; cell_id++) {
            int finalCell_id = cell_id;
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    MessageController.build().setTxPwrOffset(id, finalCell_id, value, 3);
                }
            }, delay);
            delay += 300;
        }
    }

    private void resetCellConfig(int cell) {
        checkHistoryBean.getConfig(cell).getGnb_cfg().setDl_arfcn(0);
        checkHistoryBean.getConfig(cell).getGnb_cfg().setUl_arfcn(0);
        checkHistoryBean.getConfig(cell).getGnb_cfg().setPci(0);
        checkHistoryBean.getConfig(cell).getGnb_cfg().getPlmn().clear();

        checkHistoryBean.getConfig(cell).getGnb_cfg().getSplit_cfg1().setDl_arfcn(0);
        checkHistoryBean.getConfig(cell).getGnb_cfg().getSplit_cfg1().setUl_arfcn(0);
        checkHistoryBean.getConfig(cell).getGnb_cfg().getSplit_cfg1().setPci(0);
        checkHistoryBean.getConfig(cell).getGnb_cfg().getSplit_cfg1().getPlmn().clear();

        checkHistoryBean.getConfig(cell).getGnb_cfg().getSplit_cfg2().setDl_arfcn(0);
        checkHistoryBean.getConfig(cell).getGnb_cfg().getSplit_cfg2().setUl_arfcn(0);
        checkHistoryBean.getConfig(cell).getGnb_cfg().getSplit_cfg2().setPci(0);
        checkHistoryBean.getConfig(cell).getGnb_cfg().getSplit_cfg2().getPlmn().clear();
    }

    boolean isStartCatchHandler = false;
    boolean isRsrpStart = false;
    int[] autoArfcnIndex = {0, 0, 0, 0, 0, 0};
    int[] runFailCount = new int[]{0, 0, 0, 0, 0, 0};
    int[] syncFailCount = new int[]{0, 0, 0, 0, 0, 0};
    boolean[] autoRun = {false, false, false, false, false, false};
    public int autoArfcnTime;
    public int lostTime = 0; // 掉线时间

    private void handleRunAuto(int cell_id) {
        // 不是自动模式的不走轮循
        if (resultMap == null) return;

        if (device != null && device.getWorkState() == GnbBean.State.TRACE && autoArfcnTime != 0 && lostTime > autoArfcnTime) {
            LinkedList<ArfcnPciBean> arfcnList = resultMap.get(cell_id);
            if (arfcnList == null || arfcnList.size() == 1) return;
            for (int i = 0; i < arfcnList.size(); i++) {
                if (i >= autoArfcnIndex[cell_id]) {
                    int arfcn = arfcnList.get(i).getArfcn();
                    int pci = arfcnList.get(i).getPci();
                    int band = arfcn < 100000 ? 1000 + LteBand.earfcn2band(arfcn) : NrBand.earfcn2band(arfcn);

                    // 判断是否已经在业务中
                    Gnb_cfg gnbCfg = device.getConfig(cell_id).getGnb_cfg();
                    int dlArfcn = gnbCfg.getDl_arfcn();
                    int dlSplitArfcn1 = gnbCfg.getSplit_cfg1().getDl_arfcn();
                    int dlSplitArfcn2 = gnbCfg.getSplit_cfg2().getDl_arfcn();
                    if (arfcn == dlArfcn || arfcn == dlSplitArfcn1 || arfcn == dlSplitArfcn2) {
                        if (++autoArfcnIndex[cell_id] >= arfcnList.size()) {
                            autoArfcnIndex[cell_id] = 0;
                            i = -1; //这里让i = -1，然后循环会现走i++，就会从0开始重头循环
                        }
                        if (arfcnList.size() == 3 && dlSplitArfcn2 != 0){
                            AppLog.D("mHandler same cfg " + cell_id + "， so break.");
                            break;
                        }else if (arfcnList.size() == 2 && dlSplitArfcn1 != 0){
                            AppLog.D("mHandler same cfg " + cell_id + "， so break.");
                            break;
                        }
                        AppLog.D("mHandler continue " + cell_id + ", arfcn = " + arfcn + ", pci = " + pci + ", autoArfcnIndex = " + autoArfcnIndex[cell_id] + ", size = " + arfcnList.size());
                        continue;
                    }

                    boolean isReturn = false;
                    switch (cell_id) {
                        case 0:
                            int arfcn1 = device.getConfig(1).getGnb_cfg().getDl_arfcn();
                            if (arfcn1 != 0 && band < 30){
                                int band1 = arfcn1 > 100000 ? NrBand.earfcn2band(arfcn1) : LteBand.earfcn2band(arfcn1);
                                if (band1 < 30) isReturn = true;
                            }
                            break;
                        case 1:
                            int arfcn0 = device.getConfig(0).getGnb_cfg().getDl_arfcn();
                            if (arfcn0 != 0 && band < 30){
                                int band0 = arfcn0 > 100000 ? NrBand.earfcn2band(arfcn0) : LteBand.earfcn2band(arfcn0);
                                if (band0 < 30) isReturn = true;
                            }
                    }
                    if (isReturn) {
                        if (++autoArfcnIndex[cell_id] >= resultMap.get(cell_id).size()) autoArfcnIndex[cell_id] = 0;
                        AppLog.D("mHandler isReturn " + cell_id + ", arfcn = " + arfcn + ", pci = " + pci + ", autoArfcnIndex = " + autoArfcnIndex[cell_id] + ", size = " + arfcnList.size());
                        handleRunAuto(cell_id);
                        return;
                    }
                    AppLog.D("mHandler " + cell_id + " change arfcn = " + arfcn + ", pci = " + pci + " is different band, stop at first" + ", autoArfcnIndex = " + autoArfcnIndex[cell_id]);

                    if (++autoArfcnIndex[cell_id] >= arfcnList.size()) autoArfcnIndex[cell_id] = 0;

                    resetCellConfig(cell_id);

                    checkHistoryBean.getConfig(cell_id).getGnb_cfg().setDl_arfcn(arfcn);
                    checkHistoryBean.getConfig(cell_id).getGnb_cfg().setPci(pci);

                    int cellCount = 0;
                    Gnb_cfg gnbCfgNext = checkHistoryBean.getConfig(getNextId(cell_id)).getGnb_cfg();
                    if (gnbCfgNext.getDl_arfcn() > 0) cellCount++;
                    if (gnbCfgNext.getSplit_cfg1().getDl_arfcn() > 0) cellCount++;
                    if (gnbCfgNext.getSplit_cfg2().getDl_arfcn() > 0) cellCount++;
                    boolean isSplit1 = true;
                    for (int j = i + 1; j < arfcnList.size(); j++) {
                        if (cellCount > 2) break; // 4G 两个组合小区限制只能配置4载波
                        arfcn = arfcnList.get(j).getArfcn();
                        int band_1 = arfcn < 100000 ? 1000 + LteBand.earfcn2band(arfcn) : NrBand.earfcn2band(arfcn);
                        if (band_1 != band) continue;
                        if (isSplit1) {
                            isSplit1 = false;
                            checkHistoryBean.getConfig(cell_id).getGnb_cfg().getSplit_cfg1().setDl_arfcn(arfcnList.get(j).getArfcn());
                            checkHistoryBean.getConfig(cell_id).getGnb_cfg().getSplit_cfg1().setPci(arfcnList.get(j).getPci());
                            if (arfcn > 100000) break;// 小区1 - 2不分裂双5G
                        } else {
                            if (cellCount > 1) break; // 4G 两个组合小区限制只能配置4载波
                            checkHistoryBean.getConfig(cell_id).getGnb_cfg().getSplit_cfg2().setDl_arfcn(arfcnList.get(j).getArfcn());
                            checkHistoryBean.getConfig(cell_id).getGnb_cfg().getSplit_cfg2().setPci(arfcnList.get(j).getPci());
                        }
                    }
                    autoRun[cell_id] = true;
                    MessageController.build().stopCell(device.getId(), cell_id);
                    break;
                }
            }
        }
        if (autoArfcnTime == 0) mHandler.sendEmptyMessageDelayed(cell_id, 10 * 1000L);
        else mHandler.sendEmptyMessageDelayed(cell_id, autoArfcnTime * 1000L);
    }

    @SuppressLint("HandlerLeak")
    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 0:
                case 1:
                case 2:
                case 3:
                case 4:
                case 5:
                    handleRunAuto(msg.what);
                    break;
                case 7:
                    mHandler.removeCallbacksAndMessages(null);
                    isStartCatchHandler = false;
                    device = null;
                    updateSteps(StepBean.State.success, getString(R.string.stop_work));
                    break;
                case 8:
                    if (device != null) {
                        if (device.getWorkState() == GnbBean.State.TRACE) {
                            if (mTraceChildFragment.setRsrpValue()) lostTime = 0;
                            else lostTime++; //返回false表示掉线，掉线计时增加
                        }
                        mHandler.sendEmptyMessageDelayed(8, TraceBean.RSRP_TIME_INTERVAL);
                    }
                    break;
                case 9:
                    isStartCatchHandler = false;
                    break;
            }
        }
    };

    private HistoryBean checkHistoryBean; // 当前勾选的启动项
    private boolean isInFreqForPci = false; // 标志是否在PCI自适应扫频中
    private final ArrayList<StepBean> nrStepsList = new ArrayList<>();
    public LinkedList<ScanArfcnBean> freqList = new LinkedList<>();
    public LinkedList<ScanArfcnBean> freqMSList = new LinkedList<>();
    public LinkedList<ScanArfcnBean> freqUTList = new LinkedList<>();

    public LinkedList<ScanArfcnBean> getFreqList() {
        return freqList;
    }

    public List<ImsiBean> getImsiList() {
        return mImsiList;
    }
    public List<ImsiBean> getWarningImsiList() {
        return mWarningImsiList;
    }

    public void startRunWork() {
        int checkPos = mCfgTraceChildFragment.getLastPos();
        if (checkPos == -1) {
            if (device == null) showToast(getString(R.string.dev_offline));
            else showToast(getString(R.string.check_item_tip));
            return;
        }
        mHandler.removeCallbacksAndMessages(null);
        mImsiList.clear();
        for (ImsiBean bean : mWarningImsiList) {
            bean.setUpCount(1);
            bean.setArfcn("--");
        }
        mCatchChildFragment.refreshListView();
        mWarningChildFragment.refreshListView();
        mImsiBean = null;
        mTraceChildFragment.resetRsrp(null);
        ParseDataUtil.build().initData();
        isClickStop = false;
        isRsrpStart = false;
        isStartCatchHandler = false;
        resultMap = null;
        lostTime = autoArfcnTime + 1; //避免因这个条件导致一开始无上号一直不走轮循线程
        syncFailCount = new int[]{0, 0, 0, 0, 0, 0};

        AppLog.I("startRunWork() 定位启动");
        tv_gain_btn.setTag("standard");
        tv_gain_btn.setBackgroundResource(R.drawable.btn_bg_gain);
        String sync_mode = PrefUtil.build().getString("sync_mode", "Air");
        int airSync = sync_mode.equals("Air") || sync_mode.equals(getString(R.string.air)) ? 1 : 0;

        checkHistoryBean = historyList.get(checkPos);
        boolean mob_reject_code1 = PrefUtil.build().getBoolean("mob_reject_code", false);
        int mob_reject_code = mob_reject_code1 ? 9 : 0;

        boolean force_cfg = PrefUtil.build().getBoolean("force_cfg", false);
        int i_force_cfg = force_cfg ? 1 : 0;
        for (int i = 0; i < 6; i++) {
            // 跳过列表第一个数据，取消第一个频点多一次轮询的机会
            autoArfcnIndex[i] = 1;
            runFailCount[i] = 0;
            autoRun[i] = false;
            isChangeImsi[i] = false;
            checkHistoryBean.getConfig(i).getGnb_cfg().setSync_mode(airSync);
            checkHistoryBean.getConfig(i).getGnb_cfg().setMob_reject_code(mob_reject_code);
            checkHistoryBean.getConfig(i).getGnb_cfg().setForce_cfg(i_force_cfg);
        }

        if (checkHistoryBean.getMode() == 2) { // 2 专业
            goSetParamAndRun();
        } else if (checkHistoryBean.getMode() == 3) { // 3 专业 自配置PCI

            List<Integer> list = new ArrayList<>();
            for (int i = 0; i < 6; i++) {
                TraceConfig traceConfig = checkHistoryBean.getConfig(i);
                int dlArfcn = traceConfig.getGnb_cfg().getDl_arfcn();
                if ((traceConfig.getTrace_cfg().getImsi_num() > 0 || !ZApplication.getInstance().isTrace) && dlArfcn > 0) {
                    list.add(dlArfcn);

                    int dlArfcn1 = traceConfig.getGnb_cfg().getSplit_cfg1().getDl_arfcn();
                    if (dlArfcn1 > 0) list.add(dlArfcn1);
                    int dlArfcn2 = traceConfig.getGnb_cfg().getSplit_cfg2().getDl_arfcn();
                    if (dlArfcn2 > 0) list.add(dlArfcn2);
                }
            }

            if (list.isEmpty()) {
                showToast(getString(R.string.no_imsi));
                return;
            }

            freqList.clear();
            isInFreqForPci = true;

            showToast(getString(R.string.scan_arfcn_ing), true);
            updateSteps(StepBean.State.success, getString(R.string.scan_arfcn_ing));
            setStartBtnText(getString(R.string.starting));
            tv_do_btn.setBackgroundResource(R.drawable.btn_bg_stop);
            setDevState(1, getString(R.string.working));
            view_pager.setCurrentItem(2);
            pos = 2;
            setMenuOpenMode(2);

            MessageController.build().startFreqScanByArfcn(device.getId(), 0, list);
        } else {// 0 自动、1 名单
            int type = checkHistoryBean.getMode();

            if (type < 2) {
                String tracePlmn = checkHistoryBean.getImsi().substring(0, 5);
                switch (tracePlmn) {
                    //移动
                    case "46000":
                    case "46002":
                    case "46004":
                    case "46007":
                    case "46008":
                    case "46013":
                        //广电
                    case "46015":
                        type = 0;
                        break;
                    default:
                        type = 1;
                        break;
                }
            }

            mAutoFreqDialog = new AutoFreqDialog(mContext, type);
            mAutoFreqDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
                @Override
                public void onDismiss(DialogInterface dialogInterface) {
                    autoFreqEnd();
                }
            });

            //mAutoFreqDialog.show();

            showToast(getString(R.string.scan_arfcn_ing), true);
            updateSteps(StepBean.State.success, getString(R.string.scan_arfcn_ing));
            setStartBtnText(getString(R.string.starting));
            tv_do_btn.setBackgroundResource(R.drawable.btn_bg_stop);
            setDevState(1, getString(R.string.working));
            view_pager.setCurrentItem(2);
            pos = 2;
            setMenuOpenMode(2);
        }
    }

    private boolean syncFailGoNext(int cell_id) {
        if (resultMap == null) return false;
        LinkedList<ArfcnPciBean> list = resultMap.get(cell_id);
        String errInfo = getString(R.string.air_sync_fail);
        ArfcnPciBean bean;
        // 循环两次，失败则提示失败
        if (autoArfcnIndex[cell_id] >= list.size() && runFailCount[cell_id] > 1) {
            updateSteps(StepBean.State.fail, errInfo);
            updateProgress(cell_id, getString(R.string.start_fail), true);
            MainActivity.getInstance().showToast(errInfo);
            return false;
        } else {
            if (autoArfcnIndex[cell_id] >= list.size()) autoArfcnIndex[cell_id] = 0;
            bean = list.get(autoArfcnIndex[cell_id]);
            AppLog.D("cell " + cell_id + " sync fail reset arfcn/pci = " + bean.toString() + ", runFailCount = " + runFailCount[cell_id] + ", autoArfcnIndex = " + autoArfcnIndex[cell_id]);
            updateParamAndStart(cell_id);
            autoArfcnIndex[cell_id]++;
            runFailCount[cell_id]++;
        }
        return true;
    }

    HashMap<Integer, LinkedList<ArfcnPciBean>> resultMap;

    public void autoFreqEnd() {
        if (!mAutoFreqDialog.isUserCancel()) {

            PaCtl.build().closePA(device.getId());
            int delay = 0;

            resultMap = mAutoFreqDialog.getResultMap();
            int[] cellCount = new int[]{0, 0, 0, 0, 0, 0};
            for (int i = 0; i < 6; i++) {
                LinkedList<ArfcnPciBean> list = resultMap.get(i);
                int size = list.size();

                resetCellConfig(i);

                boolean isContinue = false;
                int band = 0;
                if (size > 0) {
                    int arfcn = list.get(0).getArfcn();

                    checkHistoryBean.getConfig(i).getGnb_cfg().setDl_arfcn(list.get(0).getArfcn());
                    checkHistoryBean.getConfig(i).getGnb_cfg().setPci(list.get(0).getPci());
                    cellCount[i]++;
                    band = arfcn < 100000 ? 1000 + LteBand.earfcn2band(arfcn) : NrBand.earfcn2band(arfcn);
                    if (i > 1) {
                        if (arfcn > 100000) isContinue = true;// 小区3 - 6不分裂5G
                        else if (cellCount[i] + cellCount[getNextId(i)] > 3)
                            isContinue = true; // 4G 两个组合小区限制只能配置4载波
                    }
                }

                if (!isContinue) {
                    boolean isSplit1 = true;
                    for (int j = 1; j < size; j++) {
                        int arfcn = list.get(j).getArfcn();
                        int band_1 = arfcn < 100000 ? 1000 + LteBand.earfcn2band(arfcn) : NrBand.earfcn2band(arfcn);
                        if (band_1 != band) continue;
                        if (isSplit1) {
                            isSplit1 = false;
                            checkHistoryBean.getConfig(i).getGnb_cfg().getSplit_cfg1().setDl_arfcn(list.get(j).getArfcn());
                            checkHistoryBean.getConfig(i).getGnb_cfg().getSplit_cfg1().setPci(list.get(j).getPci());
                            cellCount[i]++;
                            if (arfcn > 100000) break;// 小区1 - 2不分裂双5G
                        } else {
                            checkHistoryBean.getConfig(i).getGnb_cfg().getSplit_cfg2().setDl_arfcn(list.get(j).getArfcn());
                            checkHistoryBean.getConfig(i).getGnb_cfg().getSplit_cfg2().setPci(list.get(j).getPci());
                            cellCount[i]++;
                        }
                        if (cellCount[i] + cellCount[getNextId(i)] > 3) break; // 4G 两个组合小区限制只能配置4载波
                    }
                }

                if (size > 0) {
                    updateParamAndStart(i);
                    if (delay == 0) freqEndGoRunWork();
                    delay += 500;
                } else device.setConfig(i, checkHistoryBean.getConfig(i));
            }
        }
        mAutoFreqDialog = null;
    }

    public int getNextId(int i) {
        int nextId = 2;
        switch (i) {
            case 5:
                nextId = 4;
                break;
            case 4:
                nextId = 5;
                break;
            case 3:
                nextId = 2;
                break;
            case 2:
                nextId = 3;
                break;
        }
        return nextId;
    }

    public void updateParamAndStart(int cell_id) {
        AppLog.D("updateParamAndStart cell_id = " + cell_id);
        TraceConfig config = checkHistoryBean.getConfig(cell_id);
        Gnb_cfg gnbCfg = config.getGnb_cfg();

        StringBuilder sb = new StringBuilder();

        // 主频点
        int dl_arfcn = gnbCfg.getDl_arfcn();
        int pci = gnbCfg.getPci();
        sb.append(dl_arfcn).append("/").append(pci).append("\n");

        int[] plmn;
        int ssb = 128;
        int bandwidth = 5;
        boolean is_lte = dl_arfcn < 100000;
        int band = is_lte ? LteBand.earfcn2band(dl_arfcn) : NrBand.earfcn2band(dl_arfcn);
        if (is_lte) {
            plmn = (band == 1 || band == 3 || band == 5 || band == 8) ? new int[]{46001, 46011} : new int[]{46000, 46015};
            if (band == 3 || band == 8) {
                int freq = LteBand.earfcn2freq(dl_arfcn);
                if ((freq > 1709 && freq < 1735) || (freq > 1804 && freq < 1830) || (freq > 888 && freq < 904) || (freq > 933 && freq < 949))
                    plmn = new int[]{46000, 46015};
            }
        } else {
            if (band < 30) {
                ssb = 240;
                bandwidth = 20;
            }else {
                ssb = 255;
                bandwidth = 100;
            }
            if (!ZApplication.getInstance().isTrace) ssb = 128;
            /*// N28使用单波束ssb = 128
            if (band == 38 || band == 41 || band == 66 || band == 78 || band == 79) {
                //ssb = 255;
                bandwidth = band == 79 ? 100 : 10;
            } else if (band == 1 || band == 3 || band == 5 || band == 7) {
                //ssb = 240;
            }*/
            plmn = (band == 1 || band == 78) ? new int[]{46001, 46011} : new int[]{46000, 46015};
        }
        PaPkUlArfcnBean paPkUlArfcn = MessageController.build().getPaPkUlArfcn(dl_arfcn, bandwidth);
        gnbCfg.setUl_arfcn(paPkUlArfcn.getUl_arfcn());
        List<Integer> plmnList = new ArrayList<>();
        plmnList.add(plmn[0]);
        plmnList.add(plmn[1]);
        gnbCfg.setPlmn(plmnList);
        // 发配置定位参数指令
        int traceTac = PrefUtil.build().getInt("tac", 12340);
        if (traceTac < 10000) traceTac = 12340;
        int maxTac = traceTac + 6;
        // 4G tac 不能大于65535， 在这4G 5G共用相同tac，因此做相同处理
        if (maxTac > 65535) {
            traceTac = 1234;// 从头再来
            maxTac = traceTac + 6;
        }
        PrefUtil.build().putInt("tac", maxTac);
        gnbCfg.setTac(maxTac);
        gnbCfg.setSsb(ssb);
        gnbCfg.setCid(55535 + maxTac);
        gnbCfg.setBandwidth(bandwidth);
        gnbCfg.setTiming_offset(GnbCity.build().getTimingOffset(is_lte ? "B" + band : "5G"));

        // 分裂频点1
        int dl_arfcn1 = gnbCfg.getSplit_cfg1().getDl_arfcn();
        if (dl_arfcn1 != 0) {
            is_lte = dl_arfcn1 < 100000;
            int split_band = is_lte ? LteBand.earfcn2band(dl_arfcn1) : NrBand.earfcn2band(dl_arfcn1);
            paPkUlArfcn = MessageController.build().getPaPkUlArfcn(dl_arfcn1, bandwidth);
            gnbCfg.getSplit_cfg1().setUl_arfcn(paPkUlArfcn.getUl_arfcn());
            if (is_lte) {
                plmn = (split_band == 1 || split_band == 3 || split_band == 5 || split_band == 8) ? new int[]{46001, 46011} : new int[]{46000, 46015};
                if (split_band == 3 || split_band == 8) {
                    int freq = LteBand.earfcn2freq(dl_arfcn1);
                    if ((freq > 1709 && freq < 1735) || (freq > 1804 && freq < 1830) || (freq > 888 && freq < 904) || (freq > 933 && freq < 949))
                        plmn = new int[]{46000, 46015};
                }
            } else {
                plmn = (split_band == 1 || split_band == 78) ? new int[]{46001, 46011} : new int[]{46000, 46015};
            }
            plmnList.clear();
            plmnList.add(plmn[0]);
            plmnList.add(plmn[1]);
            gnbCfg.getSplit_cfg1().setPlmn(plmnList);
            sb.append(dl_arfcn1).append("/").append(gnbCfg.getSplit_cfg1().getPci()).append("\n");
        }

        // 分裂频点2
        int dl_arfcn2 = gnbCfg.getSplit_cfg2().getDl_arfcn();
        if (dl_arfcn2 != 0) {
            is_lte = dl_arfcn2 < 100000;
            int split_band = is_lte ? LteBand.earfcn2band(dl_arfcn2) : NrBand.earfcn2band(dl_arfcn2);
            paPkUlArfcn = MessageController.build().getPaPkUlArfcn(dl_arfcn2, bandwidth);
            gnbCfg.getSplit_cfg2().setUl_arfcn(paPkUlArfcn.getUl_arfcn());
            if (is_lte) {
                plmn = (split_band == 1 || split_band == 3 || split_band == 5 || split_band == 8) ? new int[]{46001, 46011} : new int[]{46000, 46015};
                if (split_band == 3 || split_band == 8) {
                    int freq = LteBand.earfcn2freq(dl_arfcn2);
                    if ((freq > 1709 && freq < 1735) || (freq > 1804 && freq < 1830) || (freq > 888 && freq < 904) || (freq > 933 && freq < 949))
                        plmn = new int[]{46000, 46015};
                }
            } else {
                plmn = (split_band == 1 || split_band == 78) ? new int[]{46001, 46011} : new int[]{46000, 46015};
            }
            plmnList.clear();
            plmnList.add(plmn[0]);
            plmnList.add(plmn[1]);
            gnbCfg.getSplit_cfg2().setPlmn(plmnList);
            sb.append(dl_arfcn2).append("/").append(gnbCfg.getSplit_cfg2().getPci()).append("\n");
        }

        //mTraceChildFragment.setCfgInfo(cell_id, sb + mContext.getString(R.string.cfging), "");

        // 功放
        JsonObject gpioJson = PaCtl.build().getGpioJson(dl_arfcn, cell_id);
        config.setGnb_cfg(gnbCfg);
        config.setPa_cfg(GsonUtil.getPerson(gpioJson.toString(), Pa_cfg.class));

        config.getTac_cfg().setStart_tac(maxTac);
        config.getTac_cfg().setEnd_tac(maxTac + 10000);
        config.getTac_cfg().setTac_interval(10);

        device.setConfig(cell_id, config);

        try {
            JSONObject jsonObject;
            if (ZApplication.getInstance().isCatch){
                CatchConfig catchConfig = GsonUtil.getPerson(MessageController.build().templateCatchConfigCell().toString(), CatchConfig.class);
                TraceConfig traceConfig = device.getConfig(cell_id);
                catchConfig.setGnb_cfg(traceConfig.getGnb_cfg());
                catchConfig.setPa_cfg(traceConfig.getPa_cfg());
                catchConfig.setRf_power(traceConfig.getRf_power());
                catchConfig.getTac_cfg().setStart_tac(traceConfig.getGnb_cfg().getTac());
                catchConfig.getTac_cfg().setEnd_tac(catchConfig.getTac_cfg().getStart_tac() + 10000);
                catchConfig.getTac_cfg().setTac_interval(Integer.parseInt(PrefUtil.build().getString("tac_interval", "180")));
                jsonObject = new JSONObject(GsonUtil.createJsonString(catchConfig));
            } else if (checkHistoryBean.getMode() > 3 || !ZApplication.getInstance().isTrace) {
                // 管控
                ControlConfig controlConfig = GsonUtil.getPerson(MessageController.build().templateControlConfigCell().toString(), ControlConfig.class);
                TraceConfig traceConfig = device.getConfig(cell_id);
                controlConfig.setGnb_cfg(traceConfig.getGnb_cfg());
                controlConfig.setPa_cfg(traceConfig.getPa_cfg());
                controlConfig.setRf_power(traceConfig.getRf_power());
                controlConfig.setTac_cfg(traceConfig.getTac_cfg());
                jsonObject = new JSONObject(GsonUtil.createJsonString(controlConfig));
            } else {
                // 定位
                jsonObject = new JSONObject(GsonUtil.createJsonString(device.getConfig(cell_id)));
                mTraceChildFragment.setConfigInfo(checkHistoryBean.getImsi(), dl_arfcn);
            }
            // 第一步，配置小区
            device.setDoState(cell_id, 1);
            updateProgress(cell_id, "配置中", false);
            freshDoAllUi(cell_id);
            int delay = band < 30 ? 500 : 0; // 让FDD延迟启动，先走TDD，目的为了空口跟随
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    MessageController.build().configCell(device.getId(), cell_id, jsonObject, false);
                }
            }, delay);
            AppLog.I("updateParamAndStart configCell cell_id = " + cell_id + ", jsonObject = " + jsonObject);
            MessageController.build().writeOpLog(device.getId(), DateUtil.getCurTimeByFormat("yyyy-MM-dd HH:mm:ss") + "\t\t" + cell_id + "\t\t" + sb);
        } catch (JSONException e) {
            AppLog.E("updateParamAndStart err = " + e.getMessage());
        }
    }

    private void goSetParamAndRun() {
        PaCtl.build().closePA(device.getId());
        int delay = 0;
        for (int i = 0; i < 6; i++) {
            TraceConfig config = checkHistoryBean.getConfig(i);
            if ((config.getTrace_cfg().getImsi_num() > 0 || !ZApplication.getInstance().isTrace) && config.getGnb_cfg().getDl_arfcn() > 0 && config.getGnb_cfg().getPci() > 0) {
                updateParamAndStart(i);
                if (delay == 0) freqEndGoRunWork();
                delay += 500;
            }else device.setConfig(i, config);
        }
        if (delay == 0) showToast(getString(R.string.no_imsi));
    }

    public void freqEndGoRunWork() {
        showToast(getString(R.string.cfging_trace));
        updateSteps(StepBean.State.success, getString(R.string.cfging_trace));
        refreshTraceBtn();
    }

    boolean isClickStop = false;

    private void stopTraceDialog() {
        Dialog dialog = createDialog(false);

        View view = LayoutInflater.from(mContext).inflate(R.layout.dialog_confirm, null);
        TextView tv_title = view.findViewById(R.id.tv_title);
        tv_title.setText(getString(R.string.stop_work));
        TextView tv_msg = view.findViewById(R.id.tv_msg);
        tv_msg.setText(getString(R.string.stop_work_tip));
        final TextView btn_ok = view.findViewById(R.id.btn_ok);
        btn_ok.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                AppLog.I("stopTraceDialog onClick");
                isClickStop = true;
                mHandler.removeCallbacksAndMessages(null);
                isStartCatchHandler = false;
                setStartBtnText(getString(R.string.stoping));
                final String id = device.getId();

                for (int i = 0; i < 6; i++) {
                    isChangeImsi[i] = false;
                    autoRun[i] = false;
                    if (device.getDoState(i) == 2) {
                        updateSteps(StepBean.State.success, getString(R.string.cell) + (i + 1) + getString(R.string.cell_stoping));
                        updateProgress(i, getString(R.string.stoping), false);
                        device.setDoState(i, 3);
                        MessageController.build().stopCell(id, i);
                    }
                }

                refreshTraceBtn();
                saveDataList();
                closeDialog(dialog);
            }
        });
        view.findViewById(R.id.btn_cancel).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                closeDialog(dialog);
            }
        });

        showDialog(dialog, view, false);
    }

    public void freshDoAllUi(int cell) {
        if (mDoRfDialog != null) mDoRfDialog.freshDoAllUi(cell);
    }

    public void freshRFAllUi(int cell) {
        if (mDoRfDialog != null) mDoRfDialog.freshRFAllUi(cell);
    }

    private void refreshTraceBtn() {
        if (device == null) { // 无设备
            setStartBtnText(getString(R.string.open));
            tv_do_btn.setBackgroundResource(R.drawable.btn_bg_start);
            return;
        }

        boolean isCfging = false;
        boolean isStopping = false;
        boolean isStarted = false;
        for (int i = 0; i < 6; i++) {
            int doState = device.getDoState(i);
            if (doState == 1) {
                isCfging = true;
            } else if (doState == 3) {
                isStopping = true;
            } else if (doState == 2) {
                isStarted = true;
                device.setWorkState(GnbBean.State.TRACE);
                break;
            }
        }

        if (isStarted) setStartBtnText(getString(R.string.stop));
        else if (isCfging) setStartBtnText(getString(R.string.starting));
        else if (isStopping) setStartBtnText(getString(R.string.stoping));
        else {
            setStartBtnText(getString(R.string.open));
            device.setWorkState(GnbBean.State.IDLE);
            isClickStop = false;
        }

        if (getBtnStr().equals(getString(R.string.open))) {
            tv_do_btn.setBackgroundResource(R.drawable.btn_bg_start);
            tv_gain_btn.setVisibility(View.GONE);

            enableSpecial = false;// 停止业务恢复关闭状态
            mSlideRightFrag.setEnableSpecial();
            if (device != null && device.getWorkState() != GnbBean.State.NONE)
                setDevState(0, getString(R.string.connected));
            mCfgTraceChildFragment.setWorking(false);
        } else {
            tv_do_btn.setBackgroundResource(R.drawable.btn_bg_stop);
            tv_gain_btn.setVisibility(View.VISIBLE);
            setDevState(1, getString(R.string.working));
            mCfgTraceChildFragment.setWorking(true);
        }
    }

    private void setStartBtnText(String text) {
        tv_do_btn.setText(text);
    }

    public String getBtnStr() {
        return tv_do_btn.getText().toString();
    }

    private void setMenuOpenMode(int position) {
        if (position == 0) {
            menu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
            menu.setMode(SlidingMenu.LEFT);
        } else if (position < 3) {
            menu.setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN);
            menu.setMode(SlidingMenu.LEFT_RIGHT);
        } else {
            menu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
            menu.setMode(SlidingMenu.RIGHT);
        }
    }

    @SuppressLint("UseCompatLoadingForDrawables")
    public void setDevState(int i, String s) {
        Drawable mDrawable = null;
        int color = Color.WHITE;
        switch (i) {
            case -1:
                color = Color.parseColor("#e65c5c");
                mDrawable = getResources().getDrawable(R.mipmap.icon_home_not);
                break;
            case 0:
                mDrawable = getResources().getDrawable(R.mipmap.icon_home_ok);
                break;
            case 1:
                mDrawable = getResources().getDrawable(R.mipmap.icon_home_work);
                break;
        }

        tv_dev_state.setText(s);
        tv_dev_state.setTextColor(color);
        if (mDrawable != null)
            mDrawable.setBounds(0, 0, mDrawable.getMinimumWidth() + 10, mDrawable.getMinimumHeight() + 10);
        tv_dev_state.setCompoundDrawables(mDrawable, null, null, null);
    }

    /**
     * 初始化左右滑动菜单
     */
    SlideLeftFragment mSlideLeftFrag;
    SlideRightFragment mSlideRightFrag;
    public SlidingMenu menu;

    private void initSlideMenu() {
        menu = new SlidingMenu(this);
        // 设置触摸屏幕的模式
        menu.setTouchModeBehind(SlidingMenu.TOUCHMODE_FULLSCREEN);
        menu.setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN);
        menu.setMode(SlidingMenu.LEFT);
        menu.setShadowWidthRes(R.dimen.shadow_width);
        menu.setShadowDrawable(R.drawable.shadow_left);
        // 设置滑动菜单视图的宽度
        menu.setBehindOffsetRes(R.dimen.slidingmenu_offset);
        menu.setSecondaryShadowDrawable(R.drawable.shadow_left);//右侧菜单的阴影图片
        menu.setFadeDegree(0.35f);
        menu.attachToActivity(this, SlidingMenu.SLIDING_CONTENT);
        menu.setMenu(R.layout.slide_left_menu_frame);
        menu.setOffsetFadeDegree(0.4f);// 设置主界面剩余部分的透明的
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.id_left_menu_frame, mSlideLeftFrag = new SlideLeftFragment()).commit();

        menu.setSecondaryShadowDrawable(R.drawable.shadow_right);
        // 设置右边侧滑菜单
        menu.setSecondaryMenu(R.layout.slide_right_menu_frame);
        getSupportFragmentManager().beginTransaction().replace(R.id.id_right_menu_frame, mSlideRightFrag = new SlideRightFragment(this)).commit();

        menu.setOnClosedListener(new SlidingMenu.OnClosedListener() {
            @Override
            public void onClosed() {
                setMenuOpenMode(pos);
            }
        });
    }

    StepAdapter mStepAdapter;
    public DbManage mDbManage;

    public void showStepDialog() {
        Dialog dialog = createDialog(false);
        View view = LayoutInflater.from(mContext).inflate(R.layout.dialog_steps, null);

        // 时间线
        RecyclerView rv_steps = view.findViewById(R.id.rv_steps);

        mStepAdapter = new StepAdapter(nrStepsList);
        rv_steps.setLayoutManager(new LinearLayoutManager(mContext));
        rv_steps.setAdapter(mStepAdapter);

        view.findViewById(R.id.btn_cancel).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                closeDialog(dialog);
            }
        });
        dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
            @Override
            public void onDismiss(DialogInterface dialogInterface) {
                mStepAdapter = null;
            }
        });

        showDialog(dialog, view, false, true);
    }

    private DoRfDialog mDoRfDialog;

    public void showDoRfDialog() {
        if (device == null) {
            MainActivity.getInstance().showToast(mContext.getString(R.string.dev_not_dis));
            return;
        }
        mDoRfDialog = new DoRfDialog(mContext);
        mDoRfDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
            @Override
            public void onDismiss(DialogInterface dialogInterface) {
                mDoRfDialog = null;
            }
        });
        mDoRfDialog.show();
    }

    public boolean setFan(int speed) {
        if (device == null) {
            MainActivity.getInstance().showToast(mContext.getString(R.string.dev_not_dis));
            return false;
        }
        int[] min_temp = new int[]{-50, 40, 45, 50, 60};
        int[] max_temp = new int[]{40, 45, 50, 60, 150};
        int[] speeds = new int[]{20, 40, 60, 80, 100};
        if (speed == 50) speed = 60;//中速调为60
        if (speed == 150) MessageController.build().setFanAutoSpeed(device.getId(), min_temp, max_temp, speeds);
        else MessageController.build().setFanSpeed(device.getId(), speed);
        return true;
    }

    /**
     * 初始化对象
     */
    private void initObject() {
        AppLog.D("initObject()");
        mDbManage = DbManage.getInstance(mContext);
        historyList.addAll(mDbManage.getHistoryData());
        int lastPos = -1;
        for (int i = 0; i < historyList.size(); i++) {
            if (historyList.get(i).isChecked()) {
                lastPos = i;
                break;
            }
        }

        // 管控默认添加三项：全运营商、移动广电、联通电信
        if ((!ZApplication.getInstance().isTrace) && historyList.isEmpty()) {
            HistoryBean historyBean0 = new HistoryBean(7);
            MainActivity.getInstance().mDbManage.addHistoryData(historyBean0);

            HistoryBean historyBean1 = new HistoryBean(6);
            MainActivity.getInstance().mDbManage.addHistoryData(historyBean1);

            HistoryBean historyBean2 = new HistoryBean(5);
            MainActivity.getInstance().mDbManage.addHistoryData(historyBean2);

            HistoryBean historyBean3 = new HistoryBean(4);
            historyBean3.setChecked(true);
            MainActivity.getInstance().mDbManage.addHistoryData(historyBean3);

            historyList.add(historyBean3);
            historyList.add(historyBean2);
            historyList.add(historyBean1);
            historyList.add(historyBean0);
            // 默认选中全运营商
            lastPos = 0;
        }

        if (lastPos != -1) checkHistoryBean = historyList.get(lastPos);

        showMinRsrp = PrefUtil.build().getInt("show_min_rsrp", 20);
        isVibrate = PrefUtil.build().getBoolean("is_vibrate", true);
        isCatchAlarm = PrefUtil.build().getBoolean("is_catch_alarm", true);

        String black_list = PrefUtil.build().getString("black_list", "");
        if (!black_list.isEmpty()) {
            blackList.clear();
            blackList.addAll(GsonUtil.getPersons(black_list, MyUeidBean[].class));
        }

        String warning_list = PrefUtil.build().getString("warning_list", "");
        if (!warning_list.isEmpty()) {
            mWarningImsiList.clear();
            mWarningImsiList.addAll(GsonUtil.getPersons(warning_list, ImsiBean[].class));
            /*for (ImsiBean bean : mWarningImsiList) {
                bean.setUpCount(1);
                bean.setArfcn("--");
            }*/
        }

        GnbCity.build().init();

        dropImsiList.addAll(PrefUtil.build().getDropImsiList());

        resetAutoArfcnTime();

        mSoundUtil = new SoundUtil(this); // 提示音

        // 备注
        String imsi_notes = PrefUtil.build().getString("imsi_notes", "");
        if (imsi_notes.isEmpty()) notesMap = new HashMap<>();
        else notesMap = GsonUtil.jsonToStrMap(imsi_notes);

        String cell_manage = PrefUtil.build().getString("cell_manage", "");
        if (cell_manage.isEmpty()) {
            cellMap = new HashMap<>();
            for (int i = 0; i < 6; i++) {
                cellMap.put(i, new ArrayList<>());
            }
            showCfgCellDialog();
        } else cellMap = GsonUtil.jsonToListMap(cell_manage);

    }

    private void initArfcnData() {
        try {
            if (PrefUtil.build().getBoolean("isInitArfcn", true)){
                AppLog.I("FreqDialog initArfcnData()");
                PrefUtil.build().putBoolean("isInitArfcn", false);

                List<Integer> list = new ArrayList<>();
                // 5G
                list.add(427250);
                list.add(428910);
                list.add(422890);
                list.add(426030);
                list.add(427210);
                list.add(426750);
                list.add(422930);
                PrefUtil.build().putString("N1", Util.int2Json(list, "N1"));

                list.clear();
                list.add(154810);
                list.add(152650);
                list.add(152890);
                list.add(156970);
                list.add(154570);
                list.add(156490);
                list.add(155770);
                PrefUtil.build().putString("N28", Util.int2Json(list, "N28"));

                list.clear();
                list.add(504990);
                list.add(512910);
                list.add(516990);
                list.add(507150);
                list.add(525630);
                PrefUtil.build().putString("N41", Util.int2Json(list, "N41"));

                list.clear();
                list.add(627264);
                list.add(633984);
                PrefUtil.build().putString("N78", Util.int2Json(list, "N78"));

                list.clear();
                list.add(723360);
                PrefUtil.build().putString("N79", Util.int2Json(list, "N79"));

                // 4G
                list.clear();
                list.add(100);
                list.add(300);
                list.add(50);
                list.add(350);
                list.add(375);
                list.add(400);
                list.add(450);
                list.add(500);
                PrefUtil.build().putString("B1", Util.int2Json(list, "B1"));

                list.clear();
                list.add(1275);
                list.add(1300);
                list.add(1350);
                list.add(1506);
                list.add(1650);
                list.add(1500);
                list.add(1531);
                list.add(1524);
                list.add(1825);
                list.add(1600);
                list.add(1800);
                list.add(1850);
                PrefUtil.build().putString("B3", Util.int2Json(list, "B3"));

                list.clear();
                list.add(2452);
                PrefUtil.build().putString("B5", Util.int2Json(list, "B5"));

                list.clear();
                list.add(3125);
                list.add(3349);
                list.add(3000);
                list.add(2850);
                PrefUtil.build().putString("B7", Util.int2Json(list, "B7"));

                list.clear();
                list.add(3590);
                list.add(3682);
                list.add(3683);
                list.add(3641);
                list.add(3621);
                list.add(3725);
                list.add(3768);
                list.add(3769);
                list.add(3770);
                list.add(3775);
                list.add(3745);
                list.add(3710);
                list.add(3737);
                list.add(3740);
                PrefUtil.build().putString("B8", Util.int2Json(list, "B8"));

                list.clear();
                list.add(9410);
                list.add(9260);
                PrefUtil.build().putString("B28", Util.int2Json(list, "B7"));

                list.clear();
                list.add(36275);
                PrefUtil.build().putString("B34", Util.int2Json(list, "B34"));

                list.clear();
                list.add(38400);
                list.add(38544);
                PrefUtil.build().putString("B39", Util.int2Json(list, "B39"));

                list.clear();
                list.add(38950);
                list.add(39148);
                list.add(39292);
                list.add(38750);
                PrefUtil.build().putString("B40", Util.int2Json(list, "B40"));

                list.clear();
                list.add(40340);
                list.add(40936);
                list.add(41134);
                list.add(41332);
                PrefUtil.build().putString("B41", Util.int2Json(list, "B41"));
            }
        } catch (JSONException e) {
            AppLog.E("readArfcnData JSONException e = " + e);
        }
    }

    public void resetAutoArfcnTime() {
        String string = PrefUtil.build().getString("Auto_Arfcn_time", "0");
        if (string.isEmpty()) autoArfcnTime = 0;
        else autoArfcnTime = Integer.parseInt(string);
        scanCount = PrefUtil.build().getInt("scan_count", 2);
        nearValue = PrefUtil.build().getInt("near_value", -3);
    }

    // 》》》》》》》》》》》》》》》》》》》》》》》供Fragment 调用方法开始》》》》》》》》》》》》》》》》》》》》》》
    public void setBtnStr(boolean start) {
        if (start) {
            if (tv_do_btn.getText().equals(getString(R.string.stop))) return;
            setStartBtnText(getString(R.string.stop));
            tv_do_btn.setBackgroundResource(R.drawable.btn_bg_stop);
            tv_gain_btn.setVisibility(View.VISIBLE);
            setDevState(1, getString(R.string.working));
            mCfgTraceChildFragment.setWorking(true);
        } else {
            if (tv_do_btn.getText().equals(getString(R.string.open))) return;
            setStartBtnText(getString(R.string.open));
            tv_do_btn.setBackgroundResource(R.drawable.btn_bg_start);
            tv_gain_btn.setVisibility(View.GONE);
            if (device != null && device.getWorkState() != GnbBean.State.NONE)
                setDevState(0, getString(R.string.connected));
            mCfgTraceChildFragment.setWorking(false);
        }
    }

    /**
     * 更新连接状态
     *
     * @param state 101 连接中  103 已连接  100 未连接
     */
    public void updateConnectState(int state) {
        if (mSlideLeftFrag != null) mSlideLeftFrag.updateConnectState(state);
    }

    private void showCfgCellDialog() {
        Dialog dialog = createDialog(false);
        View view = LayoutInflater.from(mContext).inflate(R.layout.dialog_confirm, null);
        TextView tv_title = view.findViewById(R.id.tv_title);
        tv_title.setText(getString(R.string.cell_manage));
        TextView tv_msg = view.findViewById(R.id.tv_msg);
        tv_msg.setText(R.string.not_cfg_cell_tip);
        final TextView btn_ok = view.findViewById(R.id.btn_ok);
        btn_ok.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                closeDialog(dialog);
                mSlideRightFrag.showCellManageDialog();
            }
        });
        view.findViewById(R.id.btn_cancel).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                closeDialog(dialog);
            }
        });

        showDialog(dialog, view, false);
    }

    public void showFreqListDialog() {
        if (freqList.size() <= 0) {
            showToast(getString(R.string.no_freq_data));
            return;
        }
        Dialog dialog = createDialog(false);
        View view = LayoutInflater.from(mContext).inflate(R.layout.dialog_freq, null);

        TextView tv_freq_info = view.findViewById(R.id.tv_freq_info);
        tv_freq_info.setText(R.string.freq_end);
        TextView tv_freq_count = view.findViewById(R.id.tv_freq_count);
        tv_freq_count.setText("");

        RecyclerView freq_list = view.findViewById(R.id.freq_list);
        freq_list.setLayoutManager(new LinearLayoutManager(mContext));

        FreqResultListAdapter adapter = new FreqResultListAdapter(mContext, freqList, null);
        freq_list.setLayoutManager(new LinearLayoutManager(mContext));
        freq_list.setAdapter(adapter);

        TextView btn_cancel = view.findViewById(R.id.btn_cancel);
        btn_cancel.setText(R.string.back);
        btn_cancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                closeDialog(dialog);
            }
        });
        showDialog(dialog, view, false, true);
    }

    /**
     * 初始化工作加载进度条
     */
    public void initProgress() {
        String not_ready_str = getString(R.string.not_ready);
        int color = ContextCompat.getColor(mContext, R.color.color_e65c5c);
        for (int i = 0; i < 6; i++) {
            if (mSlideLeftFrag != null) mSlideLeftFrag.updateProgress(i, not_ready_str, color);
        }
    }

    /**
     * 更新工作加载进度条
     *
     * @param cell_id 小区id
     */
    public void updateProgress(int cell_id, String info, boolean isFail) {
        if (autoRun[cell_id]) return;
        int color = isFail ? ContextCompat.getColor(mContext, R.color.color_e65c5c) : ContextCompat.getColor(mContext, R.color.color_1a1a1a);
        if (mSlideLeftFrag != null) mSlideLeftFrag.updateProgress(cell_id, info, color);
    }

    @SuppressLint("NotifyDataSetChanged")
    public void updateSteps(int state, String info) {
        AppLog.I("updateSteps state = " + state + ", info = " + info);
        // 先转换第一个数据的状态，失败的不变，成功的置灰
        if (nrStepsList.size() > 0) if (nrStepsList.get(0).getState() != StepBean.State.fail)
            nrStepsList.get(0).setState(StepBean.State.success_end);
        // 插到第一个位置
        nrStepsList.add(0, new StepBean(state, DateUtil.getCurrentTime(), info));

        if (device != null) MessageController.build().writeOpLog(device.getId(), DateUtil.getCurTimeByFormat("yyyy-MM-dd HH:mm:ss") + "\t\t" + info);
        if (mStepAdapter != null) mStepAdapter.notifyDataSetChanged();
    }

    public void setChangeImsi(int cell_id, String imsi) {
        String id = device.getId();

        updateSteps(StepBean.State.success, getString(R.string.cell) + (cell_id + 1) + getString(R.string.change_imsi));
        updateProgress(cell_id, getString(R.string.changeing), false);
        device.getConfig(cell_id).getTrace_cfg().getImsi_list().get(0).setImsi(imsi);
        isChangeImsi[cell_id] = true;
        mTraceChildFragment.setConfigInfo(imsi, device.getConfig(cell_id).getGnb_cfg().getDl_arfcn());
        MessageController.build().modifyTraceTarget(id, cell_id, new UeidBean[]{new UeidBean(imsi, "")});
    }

    public void checkAndChangeImsi(String imsi) {
        boolean check = false;
        for (int i = 0; i < 6; i++) {
            if (device.getDoState(i) == 2) {
                check = true;
                setChangeImsi(i, imsi);
            }
        }
        if (check) {
            for (int j = 0; j < mImsiList.size(); j++) {
                if (mImsiList.get(j).getImsi().equals(imsi)) {
                    mImsiList.get(j).setState(IMSIState.IMSI_NOW);
                    break;
                }
            }

            for (int j = 0; j < mImsiList.size(); j++) {
                if (mImsiList.get(j).getImsi().equals(imsi)) continue;
                if (mImsiList.get(j).getState() == IMSIState.IMSI_NOW) {
                    if (MainActivity.getInstance().isInBlackList(mImsiList.get(j).getImsi()))
                        mImsiList.get(j).setState(IMSIState.IMSI_BL);
                    else mImsiList.get(j).setState(IMSIState.IMSI_OLD);
                    break;
                }
            }

            mCfgTraceChildFragment.historyAdapter.notifyDataSetChanged();
            mCatchChildFragment.refreshListView();
        }
    }

    public void addDropImsiList(String imsi) {
        if (dropImsiList.contains(imsi)) return;
        dropImsiList.add(imsi);
        if (dropImsiList.size() > 10) dropImsiList.remove(0);
        PrefUtil.build().setDropImsiList(dropImsiList);
    }

    public List<MyUeidBean> getBlackList() {
        return blackList;
    }

    public boolean addBlackList(String name, String imsi) {
        for (MyUeidBean bean : blackList) {
            if (bean.getUeidBean().getImsi().equals(imsi)) {
                return false;
            }
        }
        blackList.add(new MyUeidBean(name, new UeidBean(imsi, imsi), false, false));
        return true;
    }

    public void setBlackList(List<MyUeidBean> list) {
        blackList.clear();
        blackList.addAll(list);
    }

    public void clearBlackList() {
        blackList.clear();
    }

    public boolean isInBlackList(String imsi) {
        for (MyUeidBean bean : blackList) {
            if (bean.getUeidBean().getImsi().equals(imsi)) return true;
        }
        return false;
    }

    public boolean isInWarningImsiList(String imsi) {
        for (ImsiBean bean : mWarningImsiList) {
            if (bean.getImsi().equals(imsi)) return true;
        }
        return false;
    }

    public void deleteOrAdd(ImsiBean bean) {
        boolean isAdd = true;
        for (MyUeidBean myUeidBean : blackList) {
            if (myUeidBean.getUeidBean().getImsi().equals(bean.getImsi())) {
                isAdd = false;
                blackList.remove(myUeidBean);
                break;
            }
        }
        if (isAdd)
            blackList.add(new MyUeidBean(bean.getImsi().substring(11), new UeidBean(bean.getImsi(), ""), false, false));
        PrefUtil.build().putString("black_list", GsonUtil.createJsonString(blackList));
    }

    public void deleteOrAddWarning(ImsiBean bean) {
        boolean isAdd = true;
        for (ImsiBean myUeidBean : mWarningImsiList) {
            if (myUeidBean.getImsi().equals(bean.getImsi())) {
                isAdd = false;
                mWarningImsiList.remove(myUeidBean);
                break;
            }
        }
        if (isAdd){
            mWarningImsiList.add(new ImsiBean(IMSIState.IMSI_OLD, bean.getImsi(), "--", "", 0, System.currentTimeMillis(), 0, 0, bean.getImsi().substring(11)));
            mWarningChildFragment.refreshListView();
        }

        PrefUtil.build().putString("warning_list", GsonUtil.createJsonString(mWarningImsiList));
    }

    public void sendBlackListToDev() {
        if (device != null && device.getWorkState() == GnbBean.State.TRACE) {
            UeidBean[] ueidBeans = new UeidBean[blackList.size()];
            for (int i = 0; i < blackList.size(); i++) {
                ueidBeans[i] = blackList.get(i).getUeidBean();
            }
            for (int i = 0; i < 6; i++) {
                MessageController.build().setBlackList(device.getId(), i, ueidBeans);
            }
        }
    }

    private void stopNoUpCell() {
        boolean[] cellUp = mTraceChildFragment.getCellUp();
        AppLog.I("stopNoUpCell cellUp = " + Arrays.toString(cellUp));
        final String id = device.getId();
        for (int i = 5; i > -1; i--) {
            String stopInfo = getString(R.string.cell) + (i + 1) + getString(R.string.stop_work);
            AppLog.I("stopNoUpCell device.getDoState(i) = " + device.getDoState(i));
            if (!cellUp[i]) {
                if (device.getDoState(i) == 2) {
                    updateSteps(StepBean.State.success, stopInfo);
                    updateProgress(i, getString(R.string.stoping), false);
                    MessageController.build().stopCell(id, i);
                }
            }
        }
        refreshTraceBtn();
    }

    @Override
    public void onBusinessRsp(String id, BusinessRsp rsp) {
        Log.d("onBusinessRsp", "id = " + id + ", result = " + rsp.getResult() + ", subtype = " + rsp.getSubtype() + ", json = " + rsp.getJson());
        int cell_id;
        switch (rsp.getSubtype()) {
            case CmdConstant.Subtype.OAM_MSG_DATA_UP:
                cell_id = rsp.getCellId();

                JsonObject data = rsp.getJson();
                int arfcnInt = data.getInt("arfcn");
                String arfcn = String.valueOf(arfcnInt);
                int pciInt = data.getInt("pci");
                String pci = String.valueOf(pciInt);
                String imsi = data.getString("imsi");
                if (imsi.isEmpty()) return;
                int rsrp = (int) (data.getInt("rsrp") * 1.1 + 3);
                /*int rssi = data.getInt("rssi");
                int distance = data.getInt("distance");
                int rnti = data.getInt("rnti");*/
                int phone_type = data.getInt("phone_type"); // 苹果：2/3/4
                if (rsrp < 5) rsrp = -1;
                String traceImsi = "";
                boolean isInBlack = MainActivity.getInstance().isInBlackList(imsi); // 判断是否在白名单中
                if (ZApplication.getInstance().isTrace) {
                    if (device != null && !device.getConfig(cell_id).getTrace_cfg().getImsi_list().isEmpty())
                        traceImsi = device.getConfig(cell_id).getTrace_cfg().getImsi_list().get(0).getImsi();
                } else {
                    if (isInBlack && !ZApplication.getInstance().isCatch) return; // 白名单不显示
                    if (mImsiBean != null) traceImsi = mImsiBean.getImsi();
                }

                if (traceImsi.equals(imsi)) {
                    // 仅一个目标，全丢进小区1就好
                    ParseDataUtil.build().addDataToList(cell_id, rsrp);
                    if (!enableSpecial && phone_type > 4) {
                        enableSpecial = true;
                        mSlideRightFrag.setEnableSpecial();
                    }
                    mTraceChildFragment.setConfigInfo(cell_id, arfcn, pci);
                    mTraceChildFragment.updateCount();
                }

                long currentTimeMillis = System.currentTimeMillis();
                for (ImsiBean bean : mWarningImsiList) {
                    if (bean.getImsi().equals(imsi)){
                        bean.setUpCount(bean.getUpCount() + 1);
                        bean.setArfcn(arfcn);
                        bean.setLatestTime(currentTimeMillis);
                        mWarningChildFragment.refreshListView();
                        break;
                    }
                }
                boolean add = true;
                for (int j = 0; j < mImsiList.size(); j++) {
                    if (mImsiList.get(j).getImsi().equals(imsi)/* && mImsiList.get(j).getArfcn().equals(arfcn)*/) {
                        add = false;
                        mImsiList.get(j).setRsrp(rsrp);
                        mImsiList.get(j).setArfcn(arfcn);
                        mImsiList.get(j).setPci(pci);
                        mImsiList.get(j).setUpCount(mImsiList.get(j).getUpCount() + 1);
                        mImsiList.get(j).setLatestTime(currentTimeMillis);
                        if (traceImsi.equals(imsi))
                            mImsiList.get(j).setState(IMSIState.IMSI_NOW);
                        else if (isInBlack) mImsiList.get(j).setState(IMSIState.IMSI_BL);
                        else mImsiList.get(j).setState(IMSIState.IMSI_NEW);
                        if (phone_type > 1 && mImsiList.get(j).getPhone_type() < 2){
                            mImsiList.get(j).setPhone_type(phone_type);
                            vibrate(imsi.substring(11), phone_type);

                            if (traceImsi.equals(imsi)) mTraceChildFragment.setIphoneIcon(phone_type, rsrp);
                        }
                        break;
                    }
                }
                if (add) {
                    String nodes = notesMap.get(imsi);
                    if (nodes == null) nodes = "";
                    if (traceImsi.equals(imsi)) { // 当前定位IMSI
                        mImsiList.add(0, new ImsiBean(IMSIState.IMSI_NOW, imsi, arfcn, pci, rsrp, currentTimeMillis, cell_id, phone_type, nodes));
                    } else if (isInBlack) {
                        mImsiList.add(new ImsiBean(IMSIState.IMSI_BL, imsi, arfcn, pci, rsrp, currentTimeMillis, cell_id, phone_type, nodes));
                    } else {
                        mImsiList.add(new ImsiBean(IMSIState.IMSI_NEW, imsi, arfcn, pci, rsrp, currentTimeMillis, cell_id, phone_type, nodes));
                    }
                    if (phone_type > 1){
                        vibrate(imsi.substring(11), phone_type);

                        if (traceImsi.equals(imsi)) mTraceChildFragment.setIphoneIcon(phone_type, rsrp);
                    }
                    mCatchChildFragment.refreshListView();
                    showCatchAlarm();
                }
                if (!isStartCatchHandler) {
                    isStartCatchHandler = true;
                    mCatchChildFragment.resetShowData(); // 刷新视图
                    mHandler.sendEmptyMessageDelayed(9, 1500);
                }
                if (!isRsrpStart && rsrp > 5 && !traceImsi.isEmpty()) {
                    isRsrpStart = true;
                    mHandler.sendEmptyMessageDelayed(8, TraceBean.RSRP_TIME_INTERVAL);
                    AppLog.I("onStartTraceRsp start run 8 handler.");
                }
                break;
            case CmdConstant.Subtype.OAM_MSG_HEART_BEAT:
                if (device == null) {
                    device = new DeviceInfo(id, rsp.getJson());
                    MessageController.build().syncTime(id); // 初次，需同步单板时间

                    updateConnectState(103);
                    setDevState(0, getString(R.string.connected));

                    updateSteps(StepBean.State.success, getString(R.string.connected_dev));
                }

                if (!device.getId().equals(id)) return;

                device.setHeartbeat(rsp.getJson());
                Heartbeat heartbeat = device.getHeartbeat();

                if (heartbeat.getDev_info().getDev_state() != 0) {
                    // 非定位状态走这里
                    // 定位状态下，走GNB_STATE_PHY_ABNORMAL
                    updateSteps(StepBean.State.fail, getString(R.string.dev_err_tip));
                    if (customDialog != null) return;
                    customDialog = new CustomDialog(mContext, "系统异常", getString(R.string.dev_err_tip));
                    customDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
                        @Override
                        public void onDismiss(DialogInterface dialogInterface) {
                            customDialog = null;
                        }
                    });
                    customDialog.show();
                    //showRemindDialog("异常提示", "设备异常，须掉电重启");
                    return;
                }

                boolean isShowVolTip = false;
                double vol = (double) (heartbeat.getDev_info().getVoltage().get(1) * 310) / 210 / 1000.0;
                String tip = "";
                if (vol < 1) {
                } else if (vol < 17.5) {
                    if (tipType == 1 || tipType == 0) {
                        if (isTipCount > 6){
                            tipType = 2;
                            isShowVolTip = true;
                            if (tv_do_btn.getText().equals(getString(R.string.stop))) {
                                tip = getString(R.string.vol_min_close_tip);
                                stopNoUpCell(); // 关闭没有上号的通道
                            }else tip = getString(R.string.vol_min_tip);
                            AppLog.I("ShowVolTip second tip = " + tip);
                        }else isTipCount++;
                    }
                } else if (vol < 19.2) {
                    if (tipType == 0){
                        if (isTipCount > 3) {
                            tipType = 1;
                            isShowVolTip = true;
                            tip = getString(R.string.add_vol_tip);
                            AppLog.I("ShowVolTip first tip = " + tip);
                        }else isTipCount++;
                    } else if (tipType == 2) {
                        tipType = 1;
                        isTipCount = 4;
                    }
                } else {
                    isTipCount = 0;
                    if (tipType == 1 && vol > 18.7) tipType = 0;
                }

                if (isShowVolTip && !lastTip.equals(tip)) {
                    lastTip = tip;
                    showRemindDialog(getString(R.string.vol_min_title), tip);
                }
                if (mSlideLeftFrag != null) mSlideLeftFrag.updateState(heartbeat);
                break;
            case CmdConstant.Subtype.OAM_MSG_SYNC_TIME:
                AppLog.D("onBusinessRsp OAM_MSG_SYNC_TIME id = " + id + ", result = " + rsp.getResult());
                //showToast(rsp.getResult() == 0 ? "同步时间成功" : ErrResultInfo.getInfoByErrCode(rsp.getResult()));
                MessageController.build().getVersion(id); // 读取一次版本
                List<Cell_info> cellInfo = device.getHeartbeat().getCell_info();
                for (int i = 0; i < 6; i++) {
                    int doState = cellInfo.get(i).getCfg_state();
                    switch (doState) {
                        case 2:
                        case 3:
                        case 4:
                            device.setWorkState(GnbBean.State.TRACE);
                            MessageController.build().queryCellCfg(id, i);
                            break;
                    }
                }
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        tv_do_btn.setEnabled(true);
                    }
                }, 2000);
                break;
            case CmdConstant.Subtype.OAM_MSG_QUERY_VERSION:
                AppLog.D("onBusinessRsp OAM_MSG_QUERY_VERSION id = " + id + ", result = " + rsp.getResult() + ", json = " + rsp.getJson());
                if (rsp.getResult() == 0) {
                    JsonObject json = rsp.getJson();
                    device.setSoftVer(json.getString("sw_ver"));
                    device.setHwVer(json.getString("hw_ver"));
                    device.setFpgaVer(json.getString("fpga_ver"));
                } else showToast(ErrResultInfo.getInfoByErrCode(rsp.getResult()));
                //MessageController.build().getMqttCfg(device.getId());
                MessageController.build().getFuncCfg(device.getId(), 5613);
                MessageController.build().getFuncCfg(device.getId(), 12);
                MessageController.build().getSysInfo(device.getId());
                break;
            case CmdConstant.Subtype.OAM_MSG_QUERY_CELL:
                AppLog.D("onBusinessRsp OAM_MSG_QUERY_CELL id = " + id + ", cellId = " + rsp.getCellId() + ", result = " + rsp.getResult() + ", json = " + rsp.getJson());
                int cellId = rsp.getCellId();
                List<Cell_info> cellInfos = device.getHeartbeat().getCell_info();
                int doState = cellInfos.get(cellId).getCfg_state();
                int rfState = cellInfos.get(cellId).getRf_state();
                if (doState == 3 || doState == 4) doState = 2;
                device.setDoState(cellId, doState);
                device.setRfState(cellId, rfState == 0 ? 3 : 4);
                StringBuilder stringBuilder = new StringBuilder();
                JsonObject gnbCfg = rsp.getJson().getJsonObject("gnb_cfg");
                stringBuilder.append(gnbCfg.getInt("dl_arfcn")).append("/").append(gnbCfg.getInt("pci")).append("\n");
                JsonObject split_cfg11 = gnbCfg.getJsonObject("split_cfg1");
                if (split_cfg11 == null) {
                    JsonObject split_cfg1 = new JsonObject();
                    split_cfg1.putValue("dl_arfcn", 0);
                    split_cfg1.putValue("ul_arfcn", 0);
                    split_cfg1.putValue("pci", 0);
                    split_cfg1.putValue("plmn", new JSONArray());
                    gnbCfg.put("split_cfg1", split_cfg1);
                } else {
                    stringBuilder.append(split_cfg11.getInt("dl_arfcn")).append("/").append(split_cfg11.getInt("pci")).append("\n");
                }
                JsonObject split_cfg22 = gnbCfg.getJsonObject("split_cfg2");
                if (split_cfg22 == null) {
                    JsonObject split_cfg2 = new JsonObject();
                    split_cfg2.putValue("dl_arfcn", 0);
                    split_cfg2.putValue("ul_arfcn", 0);
                    split_cfg2.putValue("pci", 0);
                    split_cfg2.putValue("plmn", new JSONArray());
                    gnbCfg.put("split_cfg2", split_cfg2);
                } else {
                    stringBuilder.append(split_cfg22.getInt("dl_arfcn")).append("/").append(split_cfg22.getInt("pci")).append("\n");
                }
                Gnb_cfg person = GsonUtil.getPerson(gnbCfg.toString(), Gnb_cfg.class);
                device.getConfig(cellId).setGnb_cfg(person);
                if (checkHistoryBean != null) checkHistoryBean.getConfig(cellId).setGnb_cfg(person);

                if (ZApplication.getInstance().isTrace) {
                    JsonObject traceCfg = rsp.getJson().getJsonObject("trace_cfg");
                    if (traceCfg != null) {
                        Trace_cfg trace_cfg = GsonUtil.getPerson(traceCfg.toString(), Trace_cfg.class);
                        device.getConfig(cellId).setTrace_cfg(trace_cfg);
                        if (checkHistoryBean != null) checkHistoryBean.getConfig(cellId).setTrace_cfg(trace_cfg);
                        if (!trace_cfg.getImsi_list().isEmpty())
                            mTraceChildFragment.setConfigInfo(trace_cfg.getImsi_list().get(0).getImsi(), person.getDl_arfcn());
                    }
                }

                //MessageController.build().recoverTacLoop(id, rsp.getCellId());
                refreshTraceBtn();
                updateSteps(StepBean.State.success, getString(R.string.cell) + (rsp.getCellId() + 1) + getString(R.string.recover_work));
                updateProgress(rsp.getCellId(), "业务中", false);
                //mTraceChildFragment.setCfgInfo(cellId, stringBuilder + "业务中", "");
                break;
            case CmdConstant.Subtype.OAM_MSG_CFG_CELL:
                AppLog.D("onBusinessRsp OAM_MSG_CFG_CELL id = " + id + ", cellId = " + rsp.getCellId() + ", result = " + rsp.getResult() + ", json = " + rsp.getJson());
                if (rsp.getResult() == 0) {
                    if (isClickStop) {
                        //mTraceChildFragment.setCfgInfo(rsp.getCellId(), "未配置", "");
                        return;
                    }

                    // 如果有黑名单，以下示例配置
                    int size = blackList.size();
                    UeidBean[] ueidBeans = new UeidBean[size];
                    for (int i = 0; i < size; i++) {
                        ueidBeans[i] = blackList.get(i).getUeidBean();
                    }
                    MessageController.build().setBlackList(id, rsp.getCellId(), ueidBeans);

                    final String cfg_plmn_mode = PrefUtil.build().getString("cfg_plmn_mode", mContext.getString(R.string.use_def));
                    String plmns = PrefUtil.build().getString("cfg_plmn", "");
                    int[] plmnArr = null;
                    if (!plmns.isEmpty()){
                        String[] split = plmns.split(";");
                        plmnArr = new int[split.length];
                        for (int i = 0; i < split.length; i++) plmnArr[i] = Integer.parseInt(split[i]);
                    }
                    if (!cfg_plmn_mode.equals(mContext.getString(R.string.use_def)) && plmnArr != null) MessageController.build().resetPlmn(id, rsp.getCellId(), plmnArr);

                    MessageController.build().startCell(id, rsp.getCellId());
                } else {
                    String errInfo = ErrResultInfo.getInfoByErrCode(rsp.getResult());
                    showToast(errInfo);
                    //mTraceChildFragment.setCfgInfo(rsp.getCellId(), "", errInfo);
                    device.setDoState(rsp.getCellId(), 0);
                    device.setRfState(rsp.getCellId(), 0);
                    freshDoAllUi(rsp.getCellId());
                    updateSteps(StepBean.State.fail, getString(R.string.cell) + (rsp.getCellId() + 1) + errInfo);
                    updateProgress(rsp.getCellId(), "启动失败", false);
                    freshRFAllUi(rsp.getCellId());
                }
                break;
            case CmdConstant.Subtype.OAM_MSG_START_CELL:
                AppLog.D("onBusinessRsp OAM_MSG_START_CELL id = " + id + ", cellId = " + rsp.getCellId() + ", result = " + rsp.getResult() + ", json = " + rsp.getJson());
                if (rsp.getResult() == 0) {
                    //showToast(getString(R.string.cell) + (rsp.getCellId() + 1) + getString(R.string.start_success));
                    //mTraceChildFragment.setCfgInfo(rsp.getCellId(), "", "业务中");
                    device.setDoState(rsp.getCellId(), 2);
                    device.setRfState(rsp.getCellId(), 3);
                    updateSteps(StepBean.State.success, getString(R.string.cell) + (rsp.getCellId() + 1) + getString(R.string.start_success));
                    updateProgress(rsp.getCellId(), "业务中", false);

                    MessageController.build().openRF(id, rsp.getCellId());
                } else {
                    if (rsp.getResult() == 12) {
                        if (syncFailGoNext(rsp.getCellId())) return;
                    }
                    String errInfo = ErrResultInfo.getInfoByErrCode(rsp.getResult());
                    updateSteps(StepBean.State.fail, getString(R.string.cell) + (rsp.getCellId() + 1) + errInfo);
                    if (rsp.getResult() == 6) {
                        if (syncFailCount[rsp.getCellId()] == 0){
                            syncFailCount[rsp.getCellId()] = 1;
                            updateParamAndStart(rsp.getCellId());
                            return;
                        }
                        if (syncFailGoNext(rsp.getCellId())) return;
                    }
                    showToast(errInfo);
                    //mTraceChildFragment.setCfgInfo(rsp.getCellId(), "", errInfo);
                    device.setDoState(rsp.getCellId(), 0);
                    device.setRfState(rsp.getCellId(), 0);
                    updateProgress(rsp.getCellId(), "启动失败", false);
                }
                freshDoAllUi(rsp.getCellId());
                freshRFAllUi(rsp.getCellId());
                refreshTraceBtn();
                break;
            case CmdConstant.Subtype.OAM_MSG_STOP_CELL:
                AppLog.D("onBusinessRsp OAM_MSG_STOP_CELL id = " + id + ", cellId = " + rsp.getCellId() + ", result = " + rsp.getResult() + ", json = " + rsp.getJson());
                if (rsp.getResult() == 0) {
                    //showToast(getString(R.string.cell) + (rsp.getCellId() + 1 ) + getString(R.string.stop_success));
                    device.setDoState(rsp.getCellId(), 0);
                    device.setRfState(rsp.getCellId(), 0);
                    updateProgress(rsp.getCellId(), "空闲", false);
                    updateSteps(StepBean.State.success, getString(R.string.cell) + (rsp.getCellId() + 1) + getString(R.string.stop_success));
                    freshDoAllUi(rsp.getCellId());
                    freshRFAllUi(rsp.getCellId());
                    //mTraceChildFragment.setCfgInfo(rsp.getCellId(), "已结束", "");
                    AppLog.D("OAM_MSG_STOP_CELL autoRun = " + autoRun[rsp.getCellId()]);
                    if (autoRun[rsp.getCellId()]) {
                        autoRun[rsp.getCellId()] = false;
                        updateParamAndStart(rsp.getCellId()); // 轮循
                    }
                    syncFailCount[rsp.getCellId()] = 0;
                } else {
                    String errInfo = ErrResultInfo.getInfoByErrCode(rsp.getResult());
                    showToast(errInfo);
                    device.setDoState(rsp.getCellId(), 2);
                    updateSteps(StepBean.State.fail, getString(R.string.cell) + (rsp.getCellId() + 1) + errInfo);
                }
                refreshTraceBtn();
                break;
            case CmdConstant.Subtype.OAM_MSG_OPEN_RF:
                AppLog.D("onBusinessRsp OAM_MSG_OPEN_RF id = " + id + ", cellId = " + rsp.getCellId() + ", result = " + rsp.getResult() + ", json = " + rsp.getJson());
                if (rsp.getResult() == 0) {
                    //showToast("小区" + (rsp.getCellId() + 1 ) + getString(R.string.open_rf_ok));
                    updateSteps(StepBean.State.success, getString(R.string.cell) + (rsp.getCellId() + 1) + getString(R.string.open_rf_ok));
                    device.setRfState(rsp.getCellId(), 4);
                    if (checkHistoryBean.getMode() != 2 && checkHistoryBean.getMode() != 3) { // 专业模式下不走轮循
                        mHandler.removeMessages(rsp.getCellId());
                        mHandler.sendEmptyMessageDelayed(rsp.getCellId(), autoArfcnTime * 1000L);
                    }
                } else {
                    showToast(ErrResultInfo.getInfoByErrCode(rsp.getResult()));
                    updateSteps(StepBean.State.fail, getString(R.string.cell) + (rsp.getCellId() + 1) + getString(R.string.open_rf_fail));
                    device.setRfState(rsp.getCellId(), 3);
                }
                freshRFAllUi(rsp.getCellId());
                break;
            case CmdConstant.Subtype.OAM_MSG_CLOSE_RF:
                AppLog.D("onBusinessRsp OAM_MSG_CLOSE_RF id = " + id + ", cellId = " + rsp.getCellId() + ", result = " + rsp.getResult() + ", json = " + rsp.getJson());
                if (rsp.getResult() == 0) {
                    showToast(getString(R.string.cell) + (rsp.getCellId() + 1) + getString(R.string.close_rf_ok));
                    updateSteps(StepBean.State.success, getString(R.string.cell) + (rsp.getCellId() + 1) + getString(R.string.close_rf_ok));
                    device.setRfState(rsp.getCellId(), 3);
                } else {
                    showToast(ErrResultInfo.getInfoByErrCode(rsp.getResult()));
                    updateSteps(StepBean.State.fail, getString(R.string.cell) + (rsp.getCellId() + 1) + getString(R.string.close_rf_fail));
                    device.setRfState(rsp.getCellId(), 4);
                }
                refreshTraceBtn();
                freshRFAllUi(rsp.getCellId());
                break;

            case CmdConstant.Subtype.OAM_MSG_GET_LOG:
                mSlideRightFrag.onGetLogRsp(id, rsp);
                break;

            case CmdConstant.Subtype.OAM_MSG_GET_OP_LOG:
                mSlideRightFrag.onGetOpLogRsp(id, rsp);
                break;

            case CmdConstant.Subtype.OAM_MSG_REBOOT:
                AppLog.D("onBusinessRsp OAM_MSG_REBOOT id = " + id + ", result = " + rsp.getResult() + ", json = " + rsp.getJson());
                if (rsp.getResult() == 0) {
                    showRemindDialog("重启提示", "设备正在重启！");
                    onSocketStateChanged(id, 103, 100);
                } else showToast(ErrResultInfo.getInfoByErrCode(rsp.getResult()));
                break;

            case CmdConstant.Subtype.OAM_MSG_VERSION_UPGRADE:
                AppLog.D("onBusinessRsp OAM_MSG_VERSION_UPGRADE id = " + id + ", result = " + rsp.getResult() + ", json = " + rsp.getJson());
                mSlideRightFrag.onUpgradeRsp(id, rsp);
                break;
            case CmdConstant.Subtype.OAM_MSG_FREQ_RESULT:
                JsonObject json = rsp.getJson();
                if (isInFreqForPci) {
                    if (!isClickStop) {
                        if (json.getInt("type") == 1) {
                            isInFreqForPci = false;
                            LinkedList<LinkedList<ArfcnPciBean>> linkedLists = FreqUtil.build().decFreqList(freqList);
                            LinkedList<ArfcnPciBean> list = new LinkedList<>(linkedLists.get(0));
                            list.addAll(linkedLists.get(1));
                            list.addAll(linkedLists.get(2));
                            list.addAll(linkedLists.get(3));
                            list.addAll(linkedLists.get(4));
                            list.addAll(linkedLists.get(5));

                            for (int i = 0; i < 6; i++) {
                                TraceConfig traceConfig = checkHistoryBean.getConfig(i);
                                int dlArfcn = traceConfig.getGnb_cfg().getDl_arfcn();
                                if ((traceConfig.getTrace_cfg().getImsi_num() > 0 || !ZApplication.getInstance().isTrace) && dlArfcn > 0) {

                                    int dlArfcn1 = traceConfig.getGnb_cfg().getSplit_cfg1().getDl_arfcn();
                                    int dlArfcn2 = traceConfig.getGnb_cfg().getSplit_cfg2().getDl_arfcn();

                                    for (ArfcnPciBean bean : list) {
                                        if (bean.getArfcn() == dlArfcn){
                                            checkHistoryBean.getConfig(i).getGnb_cfg().setPci(bean.getPci());
                                            list.remove(bean);
                                            break;
                                        }
                                    }
                                    if (dlArfcn1 > 0){
                                        for (ArfcnPciBean bean : list) {
                                            if (bean.getArfcn() == dlArfcn1){
                                                checkHistoryBean.getConfig(i).getGnb_cfg().getSplit_cfg1().setPci(bean.getPci());
                                                list.remove(bean);
                                                break;
                                            }
                                        }
                                    }

                                    if (dlArfcn2 > 0){
                                        for (ArfcnPciBean bean : list) {
                                            if (bean.getArfcn() == dlArfcn2){
                                                checkHistoryBean.getConfig(i).getGnb_cfg().getSplit_cfg2().setPci(bean.getPci());
                                                list.remove(bean);
                                                break;
                                            }
                                        }
                                    }
                                }
                            }

                            goSetParamAndRun();
                        }
                    }
                    if (json.getInt("type") == 0) {
                        JSONArray jsonArray = json.getJSONArray("data");
                        try {
                            StringBuilder sb = new StringBuilder();
                            for (int j = 0; j < jsonArray.length(); j++) {
                                JSONObject object = jsonArray.getJSONObject(j);
                                int band = object.getInt("band");
                                int i_arfcn = object.getInt("arfcn");
                                int i_pci = object.getInt("pci");
                                int pa = object.getInt("offsetPointA");
                                int pk = object.getInt("kssb");
                                int i_rsrp = object.getInt("rsrp");
                                int priority = object.getInt("priority");
                                String tac = object.getString("tac");
                                String eci = object.getString("eci");
                                JSONArray plmn = object.getJSONArray("plmn");
                                int bandwidth = object.getInt("bandwidth");

                                sb.append("arfcn = ").append(i_arfcn).append(", rsrp = ").append(i_rsrp);

                                if (freqList.isEmpty()) {
                                    freqList.add(new ScanArfcnBean(tac, eci, plmn.toString(), i_arfcn, band, i_pci, i_rsrp, priority, pa, pk, bandwidth));
                                } else {
                                    boolean isAdd = true;
                                    for (int i = 0; i < freqList.size(); i++) {
                                        if (freqList.get(i).getDl_arfcn() == i_arfcn && freqList.get(i).getPci() == i_pci) {
                                            isAdd = false;
                                            freqList.remove(freqList.get(i));
                                            ScanArfcnBean arfcnBean = new ScanArfcnBean(tac, eci, plmn.toString(), i_arfcn, band, i_pci, i_rsrp, priority, pa, pk, bandwidth);
                                            if (tac.isEmpty() || eci.isEmpty())
                                                freqList.add(arfcnBean);
                                            else freqList.add(0, arfcnBean);
                                            break;
                                        }
                                    }
                                    if (isAdd) {
                                        ScanArfcnBean arfcnBean = new ScanArfcnBean(tac, eci, plmn.toString(), i_arfcn, band, i_pci, i_rsrp, priority, pa, pk, bandwidth);
                                        if (tac.isEmpty() || eci.isEmpty()) freqList.add(arfcnBean);
                                        else freqList.add(0, arfcnBean);
                                    }
                                }
                            }
                            AppLog.I("onFreqScanRsp() " + ", result = " + sb);

                        } catch (JSONException e) {
                            AppLog.E("onFreqScanRsp err = " + e.getMessage());
                        }
                    }
                }
                if (mAutoFreqDialog != null) mAutoFreqDialog.onFreqScanRsp(id, json);
                mSlideRightFrag.onFreqScanRsp(id, json);
                break;
            case CmdConstant.Subtype.OAM_MSG_GET_FILE:
                mSlideRightFrag.onGetFileRsp(id, rsp);
                break;
            case CmdConstant.Subtype.OAM_MSG_START_TDMEASURE:
                mSlideRightFrag.onStartTdMeasure(id, rsp.getJson());
                break;
            case CmdConstant.Subtype.OAM_MSG_CFG_TRACE:
                AppLog.D("onBusinessRsp OAM_MSG_CFG_TRACE id = " + id + ", result = " + rsp.getResult() + ", json = " + rsp.getJson());
                updateSteps(StepBean.State.success, getString(R.string.cell) + (rsp.getCellId() + 1) + (rsp.getResult() == 0 ? getString(R.string.change_ok) : getString(R.string.change_fail)));
                updateProgress(rsp.getCellId(), getString(R.string.traceing), false);
                break;
            case CmdConstant.Subtype.OAM_MSG_SET_MQTT_CFG:
                AppLog.D("onBusinessRsp OAM_MSG_SET_MQTT_CFG id = " + id + ", result = " + rsp.getResult() + ", json = " + rsp.getJson());
                if (rsp.getResult() == 0) showToast(getString(R.string.cfg_ok));
                else showToast(ErrResultInfo.getInfoByErrCode(rsp.getResult()));
                break;
            case CmdConstant.Subtype.OAM_MSG_QUERY_MQTT_CFG:
                AppLog.D("onBusinessRsp OAM_MSG_QUERY_MQTT_CFG id = " + id + ", result = " + rsp.getResult() + ", json = " + rsp.getJson());
                JsonObject mqttJson = rsp.getJson();
                int pub_enable = mqttJson.getInt("pub_enable");
                mqttConnection.getMqttBean().setPub_enable(pub_enable);
                String server_ip = mqttJson.getString("server_ip");
                if (!TextUtils.isEmpty(server_ip)){
                    String pub_client = mqttJson.getString("pub_client");
                    String pub_topic = mqttJson.getString("pub_topic");
                    String pub_user = mqttJson.getString("pub_user");
                    String pub_passwd = mqttJson.getString("pub_passwd");

                    mqttConnection.getMqttBean().setHost(server_ip);
                    mqttConnection.getMqttBean().setPub_client(pub_client);
                    mqttConnection.getMqttBean().setPub_user(pub_user);
                    mqttConnection.getMqttBean().setPub_passwd(pub_passwd);
                    if (!pub_topic.equals(mqttConnection.getMqttBean().getPub_topic())){
                        mqttConnection.getMqttBean().setPub_topic(pub_topic);
                        showToast(getString(R.string.mqtt_topic_different));
                        //openMqtt();
                    }
                }
                break;
            case CmdConstant.Subtype.OAM_MSG_FUNC:
                AppLog.D("onBusinessRsp OAM_MSG_FUNC id = " + id + ", result = " + rsp.getResult() + ", json = " + rsp.getJson());
                if (rsp.getResult() == 0) {
                    JsonObject funcJson = rsp.getJson();
                    if (funcJson == null) return;
                    int func_type = funcJson.optInt("func_type", 0);
                    int cfg_type = funcJson.optInt("cfg_type", 1);
                    int cfg_value;
                    switch (func_type){
                        case 5613:
                            // 0：未打开   1：打开苹果识别   2：仅苹果识别
                            cfg_value = funcJson.getInt("cfg_value");
                            PrefUtil.build().putInt("iphone_mode", cfg_value);
                            if (cfg_type == 0) showToast(getString(R.string.cfg_ok));
                            break;
                        case 12:
                            cfg_value = funcJson.getInt("cfg_value");
                            PrefUtil.build().putString("connect_mode", cfg_value == 1 ? getString(R.string.cable) : getString(R.string.hotspot));
                            if (cfg_type == 0) showToast(getString(R.string.cfg_ok));
                            break;
                    }
                }else showToast(ErrResultInfo.getInfoByErrCode(rsp.getResult()));
                break;
            case CmdConstant.Subtype.OAM_MSG_GET_SYS_INFO:
                AppLog.D("onBusinessRsp OAM_MSG_GET_SYS_INFO id = " + id + ", result = " + rsp.getResult() + ", json = " + rsp.getJson());
                if (rsp.getResult() == 0) {
                    JsonObject infoJson = rsp.getJson();
                    String license = infoJson.optString("license_info");
                    if (!TextUtils.isEmpty(license)) {
                        device.setLicense(license);
                        String date = "2099-12-31";
                        String useHour = "0";
                        String hour = "0";
                        int hasNum = 9999;
                        if (license.contains("EXPIRED")) {
                            String[] strings = license.split("\n");

                            for (String string : strings) {
                                if (string.contains("EXPIRED")) {
                                    if (string.contains("date")) {
                                        // 新版本
                                        String[] expired = string.substring(string.indexOf("(") + 1).split(",");
                                        String en = expired[0].trim().split(" ")[1];
                                        if (en.equals("0")) break; // 不生效，就不用走下面逻辑
                                        date = expired[1].trim().split(" ")[1];
                                        if (date.equals("0")) date = "2099-12-31";
                                        else
                                            date = date.substring(0, 4) + "-" + date.substring(4, 6) + "-" + date.substring(6);

                                        int hourIndex = expired[2].trim().indexOf('/');
                                        useHour = expired[2].trim().substring(5, hourIndex);
                                        hour = expired[2].trim().substring(hourIndex + 1, expired[2].trim().length() - 1);

                                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                                        try {
                                            Date date0 = sdf.parse(date);
                                            Date date1 = sdf.parse(sdf.format(new Date()));
                                            long lDate1 = date0.getTime();
                                            long lDate2 = date1.getTime();
                                            long dateX = dateX(lDate1, lDate2);
                                            hasNum = (int) dateX;
                                            if (lDate1 < lDate2) hasNum = 0;

                                            if (hasNum > 3 && !hour.equals("0")){
                                                int x = Integer.parseInt(hour) - Integer.parseInt(useHour);
                                                if (x <= 0) hasNum = 0;
                                                else if (x < 24 * 60) hasNum = 1;
                                                else if (x < 48 * 60) hasNum = 2;
                                                else if (x < 72 * 60) hasNum = 3;
                                            }
                                        } catch (Exception e) {
                                            AppLog.E("read license err = " + e.getMessage());
                                        }
                                    }
                                    break;
                                }
                            }
                        }
                        if (hasNum <= 3) {
                            showRemindDialog(getString(R.string.expired_title), hasNum == 0 ? getString(R.string.expired_tip) : getString(R.string.lic_has_days_tip) + hasNum);
                        }
                    }
                } else showToast(ErrResultInfo.getInfoByErrCode(rsp.getResult()));
                break;
            case CmdConstant.Subtype.OAM_MSG_SET_LIC_INFO:
                if (rsp.getResult() == 0) showToast(getString(R.string.cfg_ok));
                else showToast(ErrResultInfo.getInfoByErrCode(rsp.getResult()));
                break;
            case CmdConstant.Subtype.OAM_MSG_CFG_FTP_SERVER:
                if (rsp.getResult() == 0) {
                    showToast(getString(R.string.cfg_success));
                    MessageController.build().getFtpCfg(device.getId());
                }
                else showToast(ErrResultInfo.getInfoByErrCode(rsp.getResult()));
                break;
            case CmdConstant.Subtype.OAM_MSG_GET_FTP_SERVER:
                if (rsp.getResult() == 0) {
                    device.setFtpInfo(rsp.getJson());
                    mSlideRightFrag.showFtpDialog();
                }
                else showToast(ErrResultInfo.getInfoByErrCode(rsp.getResult()));
                break;
        }
    }

    @Override
    public void onSocketStateChanged(String id, int lastState, int newState) {
        AppLog.I("onSocketStateChange():  id = " + id + ", lastState = " + lastState + ", newState = " + newState);
        if (device == null || !device.getId().equals(id)) return;

        updateConnectState(newState);
        if (newState == ConnectConstant.STATE_CONNECTED) {
            if (device.getWorkState() == GnbBean.State.NONE) {
                mHandler.removeMessages(7);
                device.setWorkState(GnbBean.State.IDLE);
                MessageController.build().syncTime(id); // 断线、重启，再同步单板时间

                setDevState(0, getString(R.string.connected));
                updateSteps(StepBean.State.success, getString(R.string.connected_dev));
            }
        } else {
            initProgress();
            device.setWorkState(GnbBean.State.NONE);
            for (int i = 0; i < 6; i++) {
                //mTraceChildFragment.setCfgInfo(i, "未配置", "");
                device.setDoState(i, 0);
                device.setRfState(i, 0);
                freshDoAllUi(i);
                freshRFAllUi(i);
            }
            setBtnStr(false);
            mSlideRightFrag.setDeviceDis(id);
            if (mAutoFreqDialog != null) {
                mAutoFreqDialog.dismiss();
                mAutoFreqDialog = null;
            }
            String dis_str = getString(R.string.disconnect_dev);
            updateSteps(StepBean.State.fail, dis_str);
            setDevState(-1, getString(R.string.not_ready));

            showToast(dis_str);
            Message message = mHandler.obtainMessage();
            message.what = 7;
            message.obj = id;
            mHandler.sendMessageDelayed(message, 90 * 1000);
        }
    }

    public ImsiBean mImsiBean;

    public void setConfigInfo(ImsiBean bean) {
        mImsiBean = bean;
        if (bean == null) {
            mTraceChildFragment.resetRsrp(null);
            mHandler.removeMessages(8);
            isRsrpStart = false;
            return;
        }
        mTraceChildFragment.setConfigInfo(bean);
        mHandler.removeMessages(8);
        isRsrpStart = false;
        view_pager.setCurrentItem(1);
        pos = 1;
        setMenuOpenMode(pos);
    }

    public void vibrate(String imsiEnd, int phoneType) {
        if (isVibrate){
            Vibrator vib = (Vibrator) this.getSystemService(Service.VIBRATOR_SERVICE);
            vib.vibrate(1000);
            String type = (phoneType == 5 || phoneType == 12) ? "三星" : "苹果";
            TextTTS.build().play("发现" + type + "目标" + imsiEnd, false);
            AppLog.I("vibrate and say 发现" + type + "目标 = " + imsiEnd);
        }
    }

    public void showCatchAlarm(){
        if (isCatchAlarm) mSoundUtil.playSound(1);
    }

    public boolean addWarningList(String name, String imsi) {
        for (ImsiBean bean : mWarningImsiList) {
            if (bean.getImsi().equals(imsi)) {
                bean.setNotes(name);
                return false;
            }
        }
        mWarningImsiList.add(new ImsiBean(IMSIState.IMSI_OLD, imsi, "--", "", 0, System.currentTimeMillis(), 0, 0, name));
        return true;
    }

    private long dateX(long lDate1, long lDate2) {
        long diff = (lDate1 < lDate2) ? (lDate2 - lDate1) : (lDate1 - lDate2);
        long day = diff / (24 * 60 * 60 * 1000);
        long hour = diff / (60 * 60 * 1000) - day * 24;
        long min = diff / (60 * 1000) - day * 24 * 60 - hour * 60;
        long sec = diff / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60;
        AppLog.D("date1 与 date2 相差 " + day + "天" + hour + "小时" + min + "分" + sec + "秒");

        return day;
    }

    public void saveDataList() {
        mSlideRightFrag.saveDataList("AutoSave", false);
    }
}